1/*
2 * Copyright 2008-2009 Katholieke Universiteit Leuven
3 * Copyright 2010 INRIA Saclay
4 * Copyright 2012-2014 Ecole Normale Superieure
5 * Copyright 2014 INRIA Rocquencourt
6 * Copyright 2016 INRIA Paris
7 * Copyright 2016 Sven Verdoolaege
8 * Copyright 2018-2019 Cerebras Systems
9 *
10 * Use of this software is governed by the MIT license
11 *
12 * Written by Sven Verdoolaege, K.U.Leuven, Departement
13 * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
14 * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
15 * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
16 * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
17 * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
18 * B.P. 105 - 78153 Le Chesnay, France
19 * and Centre de Recherche Inria de Paris, 2 rue Simone Iff - Voie DQ12,
20 * CS 42112, 75589 Paris Cedex 12, France
21 * and Cerebras Systems, 175 S San Antonio Rd, Los Altos, CA, USA
22 */
23
24#include <string.h>
25#include <isl_ctx_private.h>
26#include <isl_map_private.h>
27#include <isl_blk.h>
28#include <isl_id_private.h>
29#include <isl/constraint.h>
30#include "isl_space_private.h"
31#include "isl_equalities.h"
32#include <isl_lp_private.h>
33#include <isl_seq.h>
34#include <isl/set.h>
35#include <isl/map.h>
36#include <isl_reordering.h>
37#include "isl_sample.h"
38#include <isl_sort.h>
39#include "isl_tab.h"
40#include <isl/vec.h>
41#include <isl_mat_private.h>
42#include <isl_vec_private.h>
43#include <isl_dim_map.h>
44#include <isl_local_space_private.h>
45#include <isl_aff_private.h>
46#include <isl_options_private.h>
47#include <isl_morph.h>
48#include <isl_val_private.h>
49#include <isl_printer_private.h>
50
51#include <bset_to_bmap.c>
52#include <bset_from_bmap.c>
53#include <set_to_map.c>
54#include <set_from_map.c>
55
56/* Treat "bset" as a basic map.
57 * Internally, isl_basic_set is defined to isl_basic_map, so in practice,
58 * this function performs a redundant cast.
59 */
60static __isl_keep const isl_basic_map *const_bset_to_bmap(
61 __isl_keep const isl_basic_set *bset)
62{
63 return (const isl_basic_map *) bset;
64}
65
66#undef TYPE
67#define TYPE isl_basic_map
68#include "has_single_reference_templ.c"
69
70static unsigned pos(__isl_keep isl_space *space, enum isl_dim_type type)
71{
72 switch (type) {
73 case isl_dim_param: return 1;
74 case isl_dim_in: return 1 + space->nparam;
75 case isl_dim_out: return 1 + space->nparam + space->n_in;
76 default: return 0;
77 }
78}
79
80isl_size isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
81 enum isl_dim_type type)
82{
83 if (!bmap)
84 return isl_size_error;
85 switch (type) {
86 case isl_dim_cst: return 1;
87 case isl_dim_param:
88 case isl_dim_in:
89 case isl_dim_out: return isl_space_dim(bmap->dim, type);
90 case isl_dim_div: return bmap->n_div;
91 case isl_dim_all: return isl_basic_map_total_dim(bmap);
92 default: return 0;
93 }
94}
95
96/* Return the space of "map".
97 */
98__isl_keep isl_space *isl_map_peek_space(__isl_keep const isl_map *map)
99{
100 return map ? map->dim : NULL;
101}
102
103/* Return the space of "set".
104 */
105__isl_keep isl_space *isl_set_peek_space(__isl_keep isl_set *set)
106{
107 return isl_map_peek_space(set_to_map(set));
108}
109
110isl_size isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
111{
112 return isl_space_dim(isl_map_peek_space(map), type);
113}
114
115isl_size isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
116{
117 return isl_map_dim(set_to_map(set), type);
118}
119
120/* Return the position of the variables of the given type
121 * within the sequence of variables of "bmap".
122 */
123isl_size isl_basic_map_var_offset(__isl_keep isl_basic_map *bmap,
124 enum isl_dim_type type)
125{
126 isl_space *space;
127
128 space = isl_basic_map_peek_space(bmap);
129 if (!space)
130 return isl_size_error;
131
132 switch (type) {
133 case isl_dim_param:
134 case isl_dim_in:
135 case isl_dim_out: return isl_space_offset(space, type);
136 case isl_dim_div: return isl_space_dim(space, isl_dim_all);
137 case isl_dim_cst:
138 default:
139 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
140 "invalid dimension type", return isl_size_error);
141 }
142}
143
144/* Return the position of the variables of the given type
145 * within the sequence of variables of "bset".
146 */
147isl_size isl_basic_set_var_offset(__isl_keep isl_basic_set *bset,
148 enum isl_dim_type type)
149{
150 return isl_basic_map_var_offset(bset_to_bmap(bset), type);
151}
152
153/* Return the position of the coefficients of the variables of the given type
154 * within the sequence of coefficients of "bmap".
155 */
156unsigned isl_basic_map_offset(__isl_keep isl_basic_map *bmap,
157 enum isl_dim_type type)
158{
159 switch (type) {
160 case isl_dim_cst: return 0;
161 case isl_dim_param:
162 case isl_dim_in:
163 case isl_dim_out:
164 case isl_dim_div: return 1 + isl_basic_map_var_offset(bmap, type);
165 default: return 0;
166 }
167}
168
169unsigned isl_basic_set_offset(__isl_keep isl_basic_set *bset,
170 enum isl_dim_type type)
171{
172 return isl_basic_map_offset(bset, type);
173}
174
175static unsigned map_offset(__isl_keep isl_map *map, enum isl_dim_type type)
176{
177 return pos(map->dim, type);
178}
179
180isl_size isl_basic_set_dim(__isl_keep isl_basic_set *bset,
181 enum isl_dim_type type)
182{
183 return isl_basic_map_dim(bset, type);
184}
185
186isl_size isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
187{
188 return isl_basic_set_dim(bset, isl_dim_set);
189}
190
191isl_size isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
192{
193 return isl_basic_set_dim(bset, isl_dim_param);
194}
195
196isl_size isl_basic_set_total_dim(__isl_keep const isl_basic_set *bset)
197{
198 return isl_basic_map_total_dim(const_bset_to_bmap(bset));
199}
200
201isl_size isl_set_n_dim(__isl_keep isl_set *set)
202{
203 return isl_set_dim(set, isl_dim_set);
204}
205
206isl_size isl_set_n_param(__isl_keep isl_set *set)
207{
208 return isl_set_dim(set, isl_dim_param);
209}
210
211isl_size isl_basic_map_total_dim(__isl_keep const isl_basic_map *bmap)
212{
213 isl_size dim;
214
215 if (!bmap)
216 return isl_size_error;
217 dim = isl_space_dim(bmap->dim, isl_dim_all);
218 if (dim < 0)
219 return isl_size_error;
220 return dim + bmap->n_div;
221}
222
223/* Return the number of equality constraints in the description of "bmap".
224 * Return isl_size_error on error.
225 */
226isl_size isl_basic_map_n_equality(__isl_keep isl_basic_map *bmap)
227{
228 if (!bmap)
229 return isl_size_error;
230 return bmap->n_eq;
231}
232
233/* Return the number of equality constraints in the description of "bset".
234 * Return isl_size_error on error.
235 */
236isl_size isl_basic_set_n_equality(__isl_keep isl_basic_set *bset)
237{
238 return isl_basic_map_n_equality(bset_to_bmap(bset));
239}
240
241/* Return the number of inequality constraints in the description of "bmap".
242 * Return isl_size_error on error.
243 */
244isl_size isl_basic_map_n_inequality(__isl_keep isl_basic_map *bmap)
245{
246 if (!bmap)
247 return isl_size_error;
248 return bmap->n_ineq;
249}
250
251/* Return the number of inequality constraints in the description of "bset".
252 * Return isl_size_error on error.
253 */
254isl_size isl_basic_set_n_inequality(__isl_keep isl_basic_set *bset)
255{
256 return isl_basic_map_n_inequality(bset_to_bmap(bset));
257}
258
259/* Do "bmap1" and "bmap2" have the same parameters?
260 */
261static isl_bool isl_basic_map_has_equal_params(__isl_keep isl_basic_map *bmap1,
262 __isl_keep isl_basic_map *bmap2)
263{
264 isl_space *space1, *space2;
265
266 space1 = isl_basic_map_peek_space(bmap1);
267 space2 = isl_basic_map_peek_space(bmap2);
268 return isl_space_has_equal_params(space1, space2);
269}
270
271/* Do "map1" and "map2" have the same parameters?
272 */
273isl_bool isl_map_has_equal_params(__isl_keep isl_map *map1,
274 __isl_keep isl_map *map2)
275{
276 isl_space *space1, *space2;
277
278 space1 = isl_map_peek_space(map1);
279 space2 = isl_map_peek_space(map2);
280 return isl_space_has_equal_params(space1, space2);
281}
282
283/* Do "map" and "set" have the same parameters?
284 */
285static isl_bool isl_map_set_has_equal_params(__isl_keep isl_map *map,
286 __isl_keep isl_set *set)
287{
288 return isl_map_has_equal_params(map, set_to_map(set));
289}
290
291/* Is the tuple of type "type" of "bmap" the same as the single tuple of "bset"?
292 */
293static isl_bool isl_basic_map_set_tuple_is_equal(__isl_keep isl_basic_map *bmap,
294 enum isl_dim_type type, __isl_keep isl_basic_set *bset)
295{
296 isl_space *bmap_space, *bset_space;
297
298 bmap_space = isl_basic_map_peek_space(bmap);
299 bset_space = isl_basic_set_peek_space(bset);
300 return isl_space_tuple_is_equal(bmap_space, type,
301 bset_space, isl_dim_set);
302}
303
304/* Is the tuple of type "type" of "map" the same as the single tuple of "set"?
305 */
306static isl_bool isl_map_set_tuple_is_equal(__isl_keep isl_map *map,
307 enum isl_dim_type type, __isl_keep isl_set *set)
308{
309 return isl_map_tuple_is_equal(map, type, set_to_map(set), isl_dim_set);
310}
311
312isl_bool isl_map_compatible_domain(__isl_keep isl_map *map,
313 __isl_keep isl_set *set)
314{
315 isl_bool m;
316 if (!map || !set)
317 return isl_bool_error;
318 m = isl_map_has_equal_params(map, set_to_map(set));
319 if (m < 0 || !m)
320 return m;
321 return isl_map_set_tuple_is_equal(map, isl_dim_in, set);
322}
323
324isl_bool isl_basic_map_compatible_domain(__isl_keep isl_basic_map *bmap,
325 __isl_keep isl_basic_set *bset)
326{
327 isl_bool m;
328 if (!bmap || !bset)
329 return isl_bool_error;
330 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
331 if (m < 0 || !m)
332 return m;
333 return isl_basic_map_set_tuple_is_equal(bmap, isl_dim_in, bset);
334}
335
336isl_bool isl_map_compatible_range(__isl_keep isl_map *map,
337 __isl_keep isl_set *set)
338{
339 isl_bool m;
340 if (!map || !set)
341 return isl_bool_error;
342 m = isl_map_has_equal_params(map, set_to_map(set));
343 if (m < 0 || !m)
344 return m;
345 return isl_map_set_tuple_is_equal(map, isl_dim_out, set);
346}
347
348isl_bool isl_basic_map_compatible_range(__isl_keep isl_basic_map *bmap,
349 __isl_keep isl_basic_set *bset)
350{
351 isl_bool m;
352 if (!bmap || !bset)
353 return isl_bool_error;
354 m = isl_basic_map_has_equal_params(bmap, bset_to_bmap(bset));
355 if (m < 0 || !m)
356 return m;
357 return isl_basic_map_set_tuple_is_equal(bmap, isl_dim_out, bset);
358}
359
360isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
361{
362 return bmap ? bmap->ctx : NULL;
363}
364
365isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
366{
367 return bset ? bset->ctx : NULL;
368}
369
370isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
371{
372 return map ? map->ctx : NULL;
373}
374
375isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
376{
377 return set ? set->ctx : NULL;
378}
379
380/* Return the space of "bmap".
381 */
382__isl_keep isl_space *isl_basic_map_peek_space(
383 __isl_keep const isl_basic_map *bmap)
384{
385 return bmap ? bmap->dim : NULL;
386}
387
388/* Return the space of "bset".
389 */
390__isl_keep isl_space *isl_basic_set_peek_space(__isl_keep isl_basic_set *bset)
391{
392 return isl_basic_map_peek_space(bset_to_bmap(bset));
393}
394
395__isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
396{
397 return isl_space_copy(isl_basic_map_peek_space(bmap));
398}
399
400__isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
401{
402 return isl_basic_map_get_space(bset_to_bmap(bset));
403}
404
405/* Return the space of "bmap".
406 * This may be either a copy or the space itself
407 * if there is only one reference to "bmap".
408 * This allows the space to be modified inplace
409 * if both the basic map and its space have only a single reference.
410 * The caller is not allowed to modify "bmap" between this call and
411 * a subsequent call to isl_basic_map_restore_space.
412 * The only exception is that isl_basic_map_free can be called instead.
413 */
414static __isl_give isl_space *isl_basic_map_take_space(
415 __isl_keep isl_basic_map *bmap)
416{
417 isl_space *space;
418
419 if (!bmap)
420 return NULL;
421 if (bmap->ref != 1)
422 return isl_basic_map_get_space(bmap);
423 space = bmap->dim;
424 bmap->dim = NULL;
425 return space;
426}
427
428/* Set the space of "bmap" to "space", where the space of "bmap" may be missing
429 * due to a preceding call to isl_basic_map_take_space.
430 * However, in this case, "bmap" only has a single reference and
431 * then the call to isl_basic_map_cow has no effect.
432 */
433static __isl_give isl_basic_map *isl_basic_map_restore_space(
434 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
435{
436 if (!bmap || !space)
437 goto error;
438
439 if (bmap->dim == space) {
440 isl_space_free(space);
441 return bmap;
442 }
443
444 bmap = isl_basic_map_cow(bmap);
445 if (!bmap)
446 goto error;
447 isl_space_free(bmap->dim);
448 bmap->dim = space;
449
450 return bmap;
451error:
452 isl_basic_map_free(bmap);
453 isl_space_free(space);
454 return NULL;
455}
456
457/* Extract the divs in "bmap" as a matrix.
458 */
459__isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
460{
461 int i;
462 isl_ctx *ctx;
463 isl_mat *div;
464 isl_size v_div;
465 unsigned cols;
466
467 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
468 if (v_div < 0)
469 return NULL;
470
471 ctx = isl_basic_map_get_ctx(bmap);
472 cols = 1 + 1 + v_div + bmap->n_div;
473 div = isl_mat_alloc(ctx, bmap->n_div, cols);
474 if (!div)
475 return NULL;
476
477 for (i = 0; i < bmap->n_div; ++i)
478 isl_seq_cpy(div->row[i], bmap->div[i], cols);
479
480 return div;
481}
482
483/* Extract the divs in "bset" as a matrix.
484 */
485__isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
486{
487 return isl_basic_map_get_divs(bset);
488}
489
490__isl_give isl_local_space *isl_basic_map_get_local_space(
491 __isl_keep isl_basic_map *bmap)
492{
493 isl_mat *div;
494
495 if (!bmap)
496 return NULL;
497
498 div = isl_basic_map_get_divs(bmap);
499 return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
500}
501
502__isl_give isl_local_space *isl_basic_set_get_local_space(
503 __isl_keep isl_basic_set *bset)
504{
505 return isl_basic_map_get_local_space(bset);
506}
507
508/* For each known div d = floor(f/m), add the constraints
509 *
510 * f - m d >= 0
511 * -(f-(m-1)) + m d >= 0
512 *
513 * Do not finalize the result.
514 */
515static __isl_give isl_basic_map *add_known_div_constraints(
516 __isl_take isl_basic_map *bmap)
517{
518 int i;
519 isl_size n_div;
520
521 n_div = isl_basic_map_dim(bmap, isl_dim_div);
522 if (n_div < 0)
523 return isl_basic_map_free(bmap);
524 if (n_div == 0)
525 return bmap;
526 bmap = isl_basic_map_cow(bmap);
527 bmap = isl_basic_map_extend_constraints(bmap, 0, 2 * n_div);
528 if (!bmap)
529 return NULL;
530 for (i = 0; i < n_div; ++i) {
531 if (isl_int_is_zero(bmap->div[i][0]))
532 continue;
533 bmap = isl_basic_map_add_div_constraints(bmap, i);
534 }
535
536 return bmap;
537}
538
539__isl_give isl_basic_map *isl_basic_map_from_local_space(
540 __isl_take isl_local_space *ls)
541{
542 int i;
543 isl_size n_div;
544 isl_basic_map *bmap;
545
546 n_div = isl_local_space_dim(ls, isl_dim_div);
547 if (n_div < 0)
548 ls = isl_local_space_free(ls);
549 if (!ls)
550 return NULL;
551
552 bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
553 n_div, 0, 2 * n_div);
554
555 for (i = 0; i < n_div; ++i)
556 if (isl_basic_map_alloc_div(bmap) < 0)
557 goto error;
558
559 for (i = 0; i < n_div; ++i)
560 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
561 bmap = add_known_div_constraints(bmap);
562
563 isl_local_space_free(ls);
564 return bmap;
565error:
566 isl_local_space_free(ls);
567 isl_basic_map_free(bmap);
568 return NULL;
569}
570
571__isl_give isl_basic_set *isl_basic_set_from_local_space(
572 __isl_take isl_local_space *ls)
573{
574 return isl_basic_map_from_local_space(ls);
575}
576
577__isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
578{
579 return isl_space_copy(isl_map_peek_space(map));
580}
581
582__isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
583{
584 if (!set)
585 return NULL;
586 return isl_space_copy(set->dim);
587}
588
589/* Return the space of "map".
590 * This may be either a copy or the space itself
591 * if there is only one reference to "map".
592 * This allows the space to be modified inplace
593 * if both the map and its space have only a single reference.
594 * The caller is not allowed to modify "map" between this call and
595 * a subsequent call to isl_map_restore_space.
596 * The only exception is that isl_map_free can be called instead.
597 */
598static __isl_give isl_space *isl_map_take_space(__isl_keep isl_map *map)
599{
600 isl_space *space;
601
602 if (!map)
603 return NULL;
604 if (map->ref != 1)
605 return isl_map_get_space(map);
606 space = map->dim;
607 map->dim = NULL;
608 return space;
609}
610
611/* Set the space of "map" to "space", where the space of "map" may be missing
612 * due to a preceding call to isl_map_take_space.
613 * However, in this case, "map" only has a single reference and
614 * then the call to isl_map_cow has no effect.
615 */
616static __isl_give isl_map *isl_map_restore_space(__isl_take isl_map *map,
617 __isl_take isl_space *space)
618{
619 if (!map || !space)
620 goto error;
621
622 if (map->dim == space) {
623 isl_space_free(space);
624 return map;
625 }
626
627 map = isl_map_cow(map);
628 if (!map)
629 goto error;
630 isl_space_free(map->dim);
631 map->dim = space;
632
633 return map;
634error:
635 isl_map_free(map);
636 isl_space_free(space);
637 return NULL;
638}
639
640__isl_give isl_basic_map *isl_basic_map_set_tuple_name(
641 __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
642{
643 isl_space *space;
644
645 space = isl_basic_map_take_space(bmap);
646 space = isl_space_set_tuple_name(space, type, s);
647 bmap = isl_basic_map_restore_space(bmap, space);
648 bmap = isl_basic_map_finalize(bmap);
649 return bmap;
650}
651
652__isl_give isl_basic_set *isl_basic_set_set_tuple_name(
653 __isl_take isl_basic_set *bset, const char *s)
654{
655 return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
656}
657
658const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
659 enum isl_dim_type type)
660{
661 return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
662}
663
664__isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
665 enum isl_dim_type type, const char *s)
666{
667 int i;
668 isl_space *space;
669
670 map = isl_map_cow(map);
671 if (!map)
672 return NULL;
673
674 for (i = 0; i < map->n; ++i) {
675 map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
676 if (!map->p[i])
677 goto error;
678 }
679
680 space = isl_map_take_space(map);
681 space = isl_space_set_tuple_name(space, type, s);
682 map = isl_map_restore_space(map, space);
683
684 return map;
685error:
686 isl_map_free(map);
687 return NULL;
688}
689
690/* Replace the identifier of the tuple of type "type" by "id".
691 */
692__isl_give isl_basic_map *isl_basic_map_set_tuple_id(
693 __isl_take isl_basic_map *bmap,
694 enum isl_dim_type type, __isl_take isl_id *id)
695{
696 isl_space *space;
697
698 space = isl_basic_map_take_space(bmap);
699 space = isl_space_set_tuple_id(space, type, id);
700 bmap = isl_basic_map_restore_space(bmap, space);
701 bmap = isl_basic_map_finalize(bmap);
702 return bmap;
703}
704
705/* Replace the identifier of the tuple by "id".
706 */
707__isl_give isl_basic_set *isl_basic_set_set_tuple_id(
708 __isl_take isl_basic_set *bset, __isl_take isl_id *id)
709{
710 return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
711}
712
713/* Does the input or output tuple have a name?
714 */
715isl_bool isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
716{
717 return map ? isl_space_has_tuple_name(map->dim, type) : isl_bool_error;
718}
719
720const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
721 enum isl_dim_type type)
722{
723 return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
724}
725
726__isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
727 const char *s)
728{
729 return set_from_map(isl_map_set_tuple_name(set_to_map(set),
730 isl_dim_set, s));
731}
732
733__isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
734 enum isl_dim_type type, __isl_take isl_id *id)
735{
736 isl_space *space;
737
738 space = isl_map_take_space(map);
739 space = isl_space_set_tuple_id(space, type, id);
740 map = isl_map_restore_space(map, space);
741
742 return isl_map_reset_space(map, isl_map_get_space(map));
743}
744
745__isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
746 __isl_take isl_id *id)
747{
748 return isl_map_set_tuple_id(set, isl_dim_set, id);
749}
750
751__isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
752 enum isl_dim_type type)
753{
754 isl_space *space;
755
756 space = isl_map_take_space(map);
757 space = isl_space_reset_tuple_id(space, type);
758 map = isl_map_restore_space(map, space);
759
760 return isl_map_reset_space(map, isl_map_get_space(map));
761}
762
763__isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
764{
765 return isl_map_reset_tuple_id(set, isl_dim_set);
766}
767
768isl_bool isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
769{
770 return map ? isl_space_has_tuple_id(map->dim, type) : isl_bool_error;
771}
772
773__isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
774 enum isl_dim_type type)
775{
776 return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
777}
778
779isl_bool isl_set_has_tuple_id(__isl_keep isl_set *set)
780{
781 return isl_map_has_tuple_id(set, isl_dim_set);
782}
783
784__isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
785{
786 return isl_map_get_tuple_id(set, isl_dim_set);
787}
788
789/* Does the set tuple have a name?
790 */
791isl_bool isl_set_has_tuple_name(__isl_keep isl_set *set)
792{
793 if (!set)
794 return isl_bool_error;
795 return isl_space_has_tuple_name(set->dim, isl_dim_set);
796}
797
798
799const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
800{
801 return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
802}
803
804const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
805{
806 return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
807}
808
809const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
810 enum isl_dim_type type, unsigned pos)
811{
812 return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
813}
814
815const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
816 enum isl_dim_type type, unsigned pos)
817{
818 return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
819}
820
821/* Does the given dimension have a name?
822 */
823isl_bool isl_map_has_dim_name(__isl_keep isl_map *map,
824 enum isl_dim_type type, unsigned pos)
825{
826 if (!map)
827 return isl_bool_error;
828 return isl_space_has_dim_name(map->dim, type, pos);
829}
830
831const char *isl_map_get_dim_name(__isl_keep isl_map *map,
832 enum isl_dim_type type, unsigned pos)
833{
834 return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
835}
836
837const char *isl_set_get_dim_name(__isl_keep isl_set *set,
838 enum isl_dim_type type, unsigned pos)
839{
840 return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
841}
842
843/* Does the given dimension have a name?
844 */
845isl_bool isl_set_has_dim_name(__isl_keep isl_set *set,
846 enum isl_dim_type type, unsigned pos)
847{
848 if (!set)
849 return isl_bool_error;
850 return isl_space_has_dim_name(set->dim, type, pos);
851}
852
853__isl_give isl_basic_map *isl_basic_map_set_dim_name(
854 __isl_take isl_basic_map *bmap,
855 enum isl_dim_type type, unsigned pos, const char *s)
856{
857 isl_space *space;
858
859 space = isl_basic_map_take_space(bmap);
860 space = isl_space_set_dim_name(space, type, pos, s);
861 bmap = isl_basic_map_restore_space(bmap, space);
862 return isl_basic_map_finalize(bmap);
863}
864
865__isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
866 enum isl_dim_type type, unsigned pos, const char *s)
867{
868 int i;
869 isl_space *space;
870
871 map = isl_map_cow(map);
872 if (!map)
873 return NULL;
874
875 for (i = 0; i < map->n; ++i) {
876 map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
877 if (!map->p[i])
878 goto error;
879 }
880
881 space = isl_map_take_space(map);
882 space = isl_space_set_dim_name(space, type, pos, s);
883 map = isl_map_restore_space(map, space);
884
885 return map;
886error:
887 isl_map_free(map);
888 return NULL;
889}
890
891__isl_give isl_basic_set *isl_basic_set_set_dim_name(
892 __isl_take isl_basic_set *bset,
893 enum isl_dim_type type, unsigned pos, const char *s)
894{
895 return bset_from_bmap(isl_basic_map_set_dim_name(bset_to_bmap(bset),
896 type, pos, s));
897}
898
899__isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
900 enum isl_dim_type type, unsigned pos, const char *s)
901{
902 return set_from_map(isl_map_set_dim_name(set_to_map(set),
903 type, pos, s));
904}
905
906isl_bool isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
907 enum isl_dim_type type, unsigned pos)
908{
909 if (!bmap)
910 return isl_bool_error;
911 return isl_space_has_dim_id(bmap->dim, type, pos);
912}
913
914__isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
915 enum isl_dim_type type, unsigned pos)
916{
917 return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
918}
919
920isl_bool isl_map_has_dim_id(__isl_keep isl_map *map,
921 enum isl_dim_type type, unsigned pos)
922{
923 return map ? isl_space_has_dim_id(map->dim, type, pos) : isl_bool_error;
924}
925
926__isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
927 enum isl_dim_type type, unsigned pos)
928{
929 return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
930}
931
932isl_bool isl_set_has_dim_id(__isl_keep isl_set *set,
933 enum isl_dim_type type, unsigned pos)
934{
935 return isl_map_has_dim_id(set, type, pos);
936}
937
938__isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
939 enum isl_dim_type type, unsigned pos)
940{
941 return isl_map_get_dim_id(set, type, pos);
942}
943
944__isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
945 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
946{
947 isl_space *space;
948
949 space = isl_map_take_space(map);
950 space = isl_space_set_dim_id(space, type, pos, id);
951 map = isl_map_restore_space(map, space);
952
953 return isl_map_reset_space(map, isl_map_get_space(map));
954}
955
956__isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
957 enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
958{
959 return isl_map_set_dim_id(set, type, pos, id);
960}
961
962int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
963 __isl_keep isl_id *id)
964{
965 if (!map)
966 return -1;
967 return isl_space_find_dim_by_id(map->dim, type, id);
968}
969
970int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
971 __isl_keep isl_id *id)
972{
973 return isl_map_find_dim_by_id(set, type, id);
974}
975
976/* Return the position of the dimension of the given type and name
977 * in "bmap".
978 * Return -1 if no such dimension can be found.
979 */
980int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
981 enum isl_dim_type type, const char *name)
982{
983 if (!bmap)
984 return -1;
985 return isl_space_find_dim_by_name(bmap->dim, type, name);
986}
987
988int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
989 const char *name)
990{
991 if (!map)
992 return -1;
993 return isl_space_find_dim_by_name(map->dim, type, name);
994}
995
996int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
997 const char *name)
998{
999 return isl_map_find_dim_by_name(set, type, name);
1000}
1001
1002/* Check whether equality i of bset is a pure stride constraint
1003 * on a single dimension, i.e., of the form
1004 *
1005 * v = k e
1006 *
1007 * with k a constant and e an existentially quantified variable.
1008 */
1009isl_bool isl_basic_set_eq_is_stride(__isl_keep isl_basic_set *bset, int i)
1010{
1011 isl_size nparam;
1012 isl_size d;
1013 isl_size n_div;
1014 int pos1;
1015 int pos2;
1016
1017 nparam = isl_basic_set_dim(bset, isl_dim_param);
1018 d = isl_basic_set_dim(bset, isl_dim_set);
1019 n_div = isl_basic_set_dim(bset, isl_dim_div);
1020 if (nparam < 0 || d < 0 || n_div < 0)
1021 return isl_bool_error;
1022
1023 if (!isl_int_is_zero(bset->eq[i][0]))
1024 return isl_bool_false;
1025
1026 if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
1027 return isl_bool_false;
1028 pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
1029 if (pos1 == -1)
1030 return isl_bool_false;
1031 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
1032 d - pos1 - 1) != -1)
1033 return isl_bool_false;
1034
1035 pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
1036 if (pos2 == -1)
1037 return isl_bool_false;
1038 if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d + pos2 + 1,
1039 n_div - pos2 - 1) != -1)
1040 return isl_bool_false;
1041 if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
1042 !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
1043 return isl_bool_false;
1044
1045 return isl_bool_true;
1046}
1047
1048/* Reset the user pointer on all identifiers of parameters and tuples
1049 * of the space of "map".
1050 */
1051__isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
1052{
1053 isl_space *space;
1054
1055 space = isl_map_get_space(map);
1056 space = isl_space_reset_user(space);
1057 map = isl_map_reset_space(map, space);
1058
1059 return map;
1060}
1061
1062/* Reset the user pointer on all identifiers of parameters and tuples
1063 * of the space of "set".
1064 */
1065__isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
1066{
1067 return isl_map_reset_user(set);
1068}
1069
1070isl_bool isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
1071{
1072 if (!bmap)
1073 return isl_bool_error;
1074 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
1075}
1076
1077/* Has "map" been marked as a rational map?
1078 * In particular, have all basic maps in "map" been marked this way?
1079 * An empty map is not considered to be rational.
1080 * Maps where only some of the basic maps are marked rational
1081 * are not allowed.
1082 */
1083isl_bool isl_map_is_rational(__isl_keep isl_map *map)
1084{
1085 int i;
1086 isl_bool rational;
1087
1088 if (!map)
1089 return isl_bool_error;
1090 if (map->n == 0)
1091 return isl_bool_false;
1092 rational = isl_basic_map_is_rational(map->p[0]);
1093 if (rational < 0)
1094 return rational;
1095 for (i = 1; i < map->n; ++i) {
1096 isl_bool rational_i;
1097
1098 rational_i = isl_basic_map_is_rational(map->p[i]);
1099 if (rational_i < 0)
1100 return rational_i;
1101 if (rational != rational_i)
1102 isl_die(isl_map_get_ctx(map), isl_error_unsupported,
1103 "mixed rational and integer basic maps "
1104 "not supported", return isl_bool_error);
1105 }
1106
1107 return rational;
1108}
1109
1110/* Has "set" been marked as a rational set?
1111 * In particular, have all basic set in "set" been marked this way?
1112 * An empty set is not considered to be rational.
1113 * Sets where only some of the basic sets are marked rational
1114 * are not allowed.
1115 */
1116isl_bool isl_set_is_rational(__isl_keep isl_set *set)
1117{
1118 return isl_map_is_rational(set);
1119}
1120
1121int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
1122{
1123 return isl_basic_map_is_rational(bset);
1124}
1125
1126/* Does "bmap" contain any rational points?
1127 *
1128 * If "bmap" has an equality for each dimension, equating the dimension
1129 * to an integer constant, then it has no rational points, even if it
1130 * is marked as rational.
1131 */
1132isl_bool isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
1133{
1134 isl_bool has_rational = isl_bool_true;
1135 isl_size total;
1136
1137 if (!bmap)
1138 return isl_bool_error;
1139 if (isl_basic_map_plain_is_empty(bmap))
1140 return isl_bool_false;
1141 if (!isl_basic_map_is_rational(bmap))
1142 return isl_bool_false;
1143 bmap = isl_basic_map_copy(bmap);
1144 bmap = isl_basic_map_implicit_equalities(bmap);
1145 total = isl_basic_map_dim(bmap, isl_dim_all);
1146 if (total < 0)
1147 return isl_bool_error;
1148 if (bmap->n_eq == total) {
1149 int i, j;
1150 for (i = 0; i < bmap->n_eq; ++i) {
1151 j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
1152 if (j < 0)
1153 break;
1154 if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
1155 !isl_int_is_negone(bmap->eq[i][1 + j]))
1156 break;
1157 j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
1158 total - j - 1);
1159 if (j >= 0)
1160 break;
1161 }
1162 if (i == bmap->n_eq)
1163 has_rational = isl_bool_false;
1164 }
1165 isl_basic_map_free(bmap);
1166
1167 return has_rational;
1168}
1169
1170/* Does "map" contain any rational points?
1171 */
1172isl_bool isl_map_has_rational(__isl_keep isl_map *map)
1173{
1174 int i;
1175 isl_bool has_rational;
1176
1177 if (!map)
1178 return isl_bool_error;
1179 for (i = 0; i < map->n; ++i) {
1180 has_rational = isl_basic_map_has_rational(map->p[i]);
1181 if (has_rational < 0 || has_rational)
1182 return has_rational;
1183 }
1184 return isl_bool_false;
1185}
1186
1187/* Does "set" contain any rational points?
1188 */
1189isl_bool isl_set_has_rational(__isl_keep isl_set *set)
1190{
1191 return isl_map_has_rational(set);
1192}
1193
1194/* Is this basic set a parameter domain?
1195 */
1196isl_bool isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
1197{
1198 if (!bset)
1199 return isl_bool_error;
1200 return isl_space_is_params(bset->dim);
1201}
1202
1203/* Is this set a parameter domain?
1204 */
1205isl_bool isl_set_is_params(__isl_keep isl_set *set)
1206{
1207 if (!set)
1208 return isl_bool_error;
1209 return isl_space_is_params(set->dim);
1210}
1211
1212/* Is this map actually a parameter domain?
1213 * Users should never call this function. Outside of isl,
1214 * a map can never be a parameter domain.
1215 */
1216isl_bool isl_map_is_params(__isl_keep isl_map *map)
1217{
1218 if (!map)
1219 return isl_bool_error;
1220 return isl_space_is_params(map->dim);
1221}
1222
1223static __isl_give isl_basic_map *basic_map_init(isl_ctx *ctx,
1224 __isl_take isl_basic_map *bmap, unsigned extra,
1225 unsigned n_eq, unsigned n_ineq)
1226{
1227 int i;
1228 isl_space *space = isl_basic_map_peek_space(bmap);
1229 isl_size n_var = isl_space_dim(space, isl_dim_all);
1230 size_t row_size = 1 + n_var + extra;
1231
1232 bmap->ctx = ctx;
1233 isl_ctx_ref(ctx);
1234
1235 if (n_var < 0)
1236 return isl_basic_map_free(bmap);
1237
1238 bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
1239 if (isl_blk_is_error(bmap->block))
1240 goto error;
1241
1242 bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
1243 if ((n_ineq + n_eq) && !bmap->ineq)
1244 goto error;
1245
1246 if (extra == 0) {
1247 bmap->block2 = isl_blk_empty();
1248 bmap->div = NULL;
1249 } else {
1250 bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
1251 if (isl_blk_is_error(bmap->block2))
1252 goto error;
1253
1254 bmap->div = isl_alloc_array(ctx, isl_int *, extra);
1255 if (!bmap->div)
1256 goto error;
1257 }
1258
1259 for (i = 0; i < n_ineq + n_eq; ++i)
1260 bmap->ineq[i] = bmap->block.data + i * row_size;
1261
1262 for (i = 0; i < extra; ++i)
1263 bmap->div[i] = bmap->block2.data + i * (1 + row_size);
1264
1265 bmap->ref = 1;
1266 bmap->flags = 0;
1267 bmap->c_size = n_eq + n_ineq;
1268 bmap->eq = bmap->ineq + n_ineq;
1269 bmap->extra = extra;
1270 bmap->n_eq = 0;
1271 bmap->n_ineq = 0;
1272 bmap->n_div = 0;
1273 bmap->sample = NULL;
1274
1275 return bmap;
1276error:
1277 isl_basic_map_free(bmap);
1278 return NULL;
1279}
1280
1281__isl_give isl_basic_set *isl_basic_set_alloc(isl_ctx *ctx,
1282 unsigned nparam, unsigned dim, unsigned extra,
1283 unsigned n_eq, unsigned n_ineq)
1284{
1285 struct isl_basic_map *bmap;
1286 isl_space *space;
1287
1288 space = isl_space_set_alloc(ctx, nparam, dim);
1289 if (!space)
1290 return NULL;
1291
1292 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1293 return bset_from_bmap(bmap);
1294}
1295
1296__isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *space,
1297 unsigned extra, unsigned n_eq, unsigned n_ineq)
1298{
1299 struct isl_basic_map *bmap;
1300 if (!space)
1301 return NULL;
1302 isl_assert(space->ctx, space->n_in == 0, goto error);
1303 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1304 return bset_from_bmap(bmap);
1305error:
1306 isl_space_free(space);
1307 return NULL;
1308}
1309
1310__isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *space,
1311 unsigned extra, unsigned n_eq, unsigned n_ineq)
1312{
1313 struct isl_basic_map *bmap;
1314
1315 if (!space)
1316 return NULL;
1317 bmap = isl_calloc_type(space->ctx, struct isl_basic_map);
1318 if (!bmap)
1319 goto error;
1320 bmap->dim = space;
1321
1322 return basic_map_init(space->ctx, bmap, extra, n_eq, n_ineq);
1323error:
1324 isl_space_free(space);
1325 return NULL;
1326}
1327
1328__isl_give isl_basic_map *isl_basic_map_alloc(isl_ctx *ctx,
1329 unsigned nparam, unsigned in, unsigned out, unsigned extra,
1330 unsigned n_eq, unsigned n_ineq)
1331{
1332 struct isl_basic_map *bmap;
1333 isl_space *space;
1334
1335 space = isl_space_alloc(ctx, nparam, in, out);
1336 if (!space)
1337 return NULL;
1338
1339 bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1340 return bmap;
1341}
1342
1343static __isl_give isl_basic_map *dup_constraints(__isl_take isl_basic_map *dst,
1344 __isl_keep isl_basic_map *src)
1345{
1346 int i;
1347 isl_size total = isl_basic_map_dim(src, isl_dim_all);
1348
1349 if (!dst || total < 0)
1350 return isl_basic_map_free(dst);
1351
1352 for (i = 0; i < src->n_eq; ++i) {
1353 int j = isl_basic_map_alloc_equality(dst);
1354 if (j < 0)
1355 return isl_basic_map_free(dst);
1356 isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
1357 }
1358
1359 for (i = 0; i < src->n_ineq; ++i) {
1360 int j = isl_basic_map_alloc_inequality(dst);
1361 if (j < 0)
1362 return isl_basic_map_free(dst);
1363 isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
1364 }
1365
1366 for (i = 0; i < src->n_div; ++i) {
1367 int j = isl_basic_map_alloc_div(dst);
1368 if (j < 0)
1369 return isl_basic_map_free(dst);
1370 isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
1371 }
1372 ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
1373 return dst;
1374}
1375
1376__isl_give isl_basic_map *isl_basic_map_dup(__isl_keep isl_basic_map *bmap)
1377{
1378 struct isl_basic_map *dup;
1379
1380 if (!bmap)
1381 return NULL;
1382 dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
1383 bmap->n_div, bmap->n_eq, bmap->n_ineq);
1384 dup = dup_constraints(dup, bmap);
1385 if (!dup)
1386 return NULL;
1387 dup->flags = bmap->flags;
1388 dup->sample = isl_vec_copy(bmap->sample);
1389 return dup;
1390}
1391
1392__isl_give isl_basic_set *isl_basic_set_dup(__isl_keep isl_basic_set *bset)
1393{
1394 struct isl_basic_map *dup;
1395
1396 dup = isl_basic_map_dup(bset_to_bmap(bset));
1397 return bset_from_bmap(dup);
1398}
1399
1400__isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset)
1401{
1402 if (!bset)
1403 return NULL;
1404
1405 if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
1406 bset->ref++;
1407 return bset;
1408 }
1409 return isl_basic_set_dup(bset);
1410}
1411
1412__isl_give isl_set *isl_set_copy(__isl_keep isl_set *set)
1413{
1414 if (!set)
1415 return NULL;
1416
1417 set->ref++;
1418 return set;
1419}
1420
1421__isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap)
1422{
1423 if (!bmap)
1424 return NULL;
1425
1426 if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
1427 bmap->ref++;
1428 return bmap;
1429 }
1430 bmap = isl_basic_map_dup(bmap);
1431 if (bmap)
1432 ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
1433 return bmap;
1434}
1435
1436__isl_give isl_map *isl_map_copy(__isl_keep isl_map *map)
1437{
1438 if (!map)
1439 return NULL;
1440
1441 map->ref++;
1442 return map;
1443}
1444
1445__isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
1446{
1447 if (!bmap)
1448 return NULL;
1449
1450 if (--bmap->ref > 0)
1451 return NULL;
1452
1453 isl_ctx_deref(bmap->ctx);
1454 free(bmap->div);
1455 isl_blk_free(bmap->ctx, bmap->block2);
1456 free(bmap->ineq);
1457 isl_blk_free(bmap->ctx, bmap->block);
1458 isl_vec_free(bmap->sample);
1459 isl_space_free(bmap->dim);
1460 free(bmap);
1461
1462 return NULL;
1463}
1464
1465__isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
1466{
1467 return isl_basic_map_free(bset_to_bmap(bset));
1468}
1469
1470static int room_for_con(__isl_keep isl_basic_map *bmap, unsigned n)
1471{
1472 return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
1473}
1474
1475/* Check that "bset" does not involve any parameters.
1476 */
1477isl_stat isl_basic_set_check_no_params(__isl_keep isl_basic_set *bset)
1478{
1479 isl_size nparam;
1480
1481 nparam = isl_basic_set_dim(bset, isl_dim_param);
1482 if (nparam < 0)
1483 return isl_stat_error;
1484 if (nparam != 0)
1485 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1486 "basic set should not have any parameters",
1487 return isl_stat_error);
1488 return isl_stat_ok;
1489}
1490
1491/* Check that "bset" does not involve any local variables.
1492 */
1493isl_stat isl_basic_set_check_no_locals(__isl_keep isl_basic_set *bset)
1494{
1495 isl_size n_div;
1496
1497 n_div = isl_basic_set_dim(bset, isl_dim_div);
1498 if (n_div < 0)
1499 return isl_stat_error;
1500 if (n_div != 0)
1501 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
1502 "basic set should not have any local variables",
1503 return isl_stat_error);
1504 return isl_stat_ok;
1505}
1506
1507#undef TYPE
1508#define TYPE isl_map
1509
1510#include "isl_check_named_params_templ.c"
1511
1512#undef TYPE
1513#define TYPE isl_basic_map
1514
1515static
1516#include "isl_check_named_params_templ.c"
1517
1518/* Check that "bmap1" and "bmap2" have the same parameters,
1519 * reporting an error if they do not.
1520 */
1521static isl_stat isl_basic_map_check_equal_params(
1522 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
1523{
1524 isl_bool match;
1525
1526 match = isl_basic_map_has_equal_params(bmap1, bmap2);
1527 if (match < 0)
1528 return isl_stat_error;
1529 if (!match)
1530 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
1531 "parameters don't match", return isl_stat_error);
1532 return isl_stat_ok;
1533}
1534
1535#undef TYPE
1536#define TYPE isl_map
1537
1538#include "isl_align_params_bin_templ.c"
1539
1540#undef SUFFIX
1541#define SUFFIX set
1542#undef ARG1
1543#define ARG1 isl_map
1544#undef ARG2
1545#define ARG2 isl_set
1546
1547#include "isl_align_params_templ.c"
1548
1549isl_bool isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
1550 __isl_keep isl_map *map2,
1551 isl_bool (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
1552{
1553 isl_bool r;
1554
1555 if (!map1 || !map2)
1556 return isl_bool_error;
1557 if (isl_map_has_equal_params(map1, map2))
1558 return fn(map1, map2);
1559 if (isl_map_check_named_params(map1) < 0)
1560 return isl_bool_error;
1561 if (isl_map_check_named_params(map2) < 0)
1562 return isl_bool_error;
1563 map1 = isl_map_copy(map1);
1564 map2 = isl_map_copy(map2);
1565 map1 = isl_map_align_params(map1, isl_map_get_space(map2));
1566 map2 = isl_map_align_params(map2, isl_map_get_space(map1));
1567 r = fn(map1, map2);
1568 isl_map_free(map1);
1569 isl_map_free(map2);
1570 return r;
1571}
1572
1573int isl_basic_map_alloc_equality(__isl_keep isl_basic_map *bmap)
1574{
1575 isl_size total;
1576 struct isl_ctx *ctx;
1577
1578 total = isl_basic_map_dim(bmap, isl_dim_all);
1579 if (total < 0)
1580 return -1;
1581 ctx = bmap->ctx;
1582 isl_assert(ctx, room_for_con(bmap, 1), return -1);
1583 isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
1584 return -1);
1585 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1586 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1587 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1588 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1589 if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
1590 isl_int *t;
1591 int j = isl_basic_map_alloc_inequality(bmap);
1592 if (j < 0)
1593 return -1;
1594 t = bmap->ineq[j];
1595 bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
1596 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1597 bmap->eq[-1] = t;
1598 bmap->n_eq++;
1599 bmap->n_ineq--;
1600 bmap->eq--;
1601 return 0;
1602 }
1603 isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + total,
1604 bmap->extra - bmap->n_div);
1605 return bmap->n_eq++;
1606}
1607
1608int isl_basic_set_alloc_equality(__isl_keep isl_basic_set *bset)
1609{
1610 return isl_basic_map_alloc_equality(bset_to_bmap(bset));
1611}
1612
1613__isl_give isl_basic_map *isl_basic_map_free_equality(
1614 __isl_take isl_basic_map *bmap, unsigned n)
1615{
1616 if (!bmap)
1617 return NULL;
1618 if (n > bmap->n_eq)
1619 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1620 "invalid number of equalities",
1621 isl_basic_map_free(bmap));
1622 bmap->n_eq -= n;
1623 return bmap;
1624}
1625
1626__isl_give isl_basic_set *isl_basic_set_free_equality(
1627 __isl_take isl_basic_set *bset, unsigned n)
1628{
1629 return bset_from_bmap(isl_basic_map_free_equality(bset_to_bmap(bset),
1630 n));
1631}
1632
1633/* Drop the equality constraint at position "pos",
1634 * preserving the order of the other equality constraints.
1635 */
1636int isl_basic_map_drop_equality(__isl_keep isl_basic_map *bmap, unsigned pos)
1637{
1638 isl_int *t;
1639 int r;
1640
1641 if (!bmap)
1642 return -1;
1643 isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
1644
1645 t = bmap->eq[pos];
1646 bmap->n_eq--;
1647 for (r = pos; r < bmap->n_eq; ++r)
1648 bmap->eq[r] = bmap->eq[r + 1];
1649 bmap->eq[bmap->n_eq] = t;
1650
1651 return 0;
1652}
1653
1654/* Turn inequality "pos" of "bmap" into an equality.
1655 *
1656 * In particular, we move the inequality in front of the equalities
1657 * and move the last inequality in the position of the moved inequality.
1658 * Note that isl_tab_make_equalities_explicit depends on this particular
1659 * change in the ordering of the constraints.
1660 */
1661void isl_basic_map_inequality_to_equality(
1662 __isl_keep isl_basic_map *bmap, unsigned pos)
1663{
1664 isl_int *t;
1665
1666 t = bmap->ineq[pos];
1667 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1668 bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
1669 bmap->eq[-1] = t;
1670 bmap->n_eq++;
1671 bmap->n_ineq--;
1672 bmap->eq--;
1673 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1674 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1675 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1676 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1677}
1678
1679static int room_for_ineq(__isl_keep isl_basic_map *bmap, unsigned n)
1680{
1681 return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
1682}
1683
1684int isl_basic_map_alloc_inequality(__isl_keep isl_basic_map *bmap)
1685{
1686 isl_size total;
1687 struct isl_ctx *ctx;
1688
1689 total = isl_basic_map_dim(bmap, isl_dim_all);
1690 if (total < 0)
1691 return -1;
1692 ctx = bmap->ctx;
1693 isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
1694 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
1695 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
1696 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1697 ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
1698 isl_seq_clr(bmap->ineq[bmap->n_ineq] + 1 + total,
1699 bmap->extra - bmap->n_div);
1700 return bmap->n_ineq++;
1701}
1702
1703int isl_basic_set_alloc_inequality(__isl_keep isl_basic_set *bset)
1704{
1705 return isl_basic_map_alloc_inequality(bset_to_bmap(bset));
1706}
1707
1708__isl_give isl_basic_map *isl_basic_map_free_inequality(
1709 __isl_take isl_basic_map *bmap, unsigned n)
1710{
1711 if (!bmap)
1712 return NULL;
1713 if (n > bmap->n_ineq)
1714 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1715 "invalid number of inequalities",
1716 return isl_basic_map_free(bmap));
1717 bmap->n_ineq -= n;
1718 return bmap;
1719}
1720
1721__isl_give isl_basic_set *isl_basic_set_free_inequality(
1722 __isl_take isl_basic_set *bset, unsigned n)
1723{
1724 return bset_from_bmap(isl_basic_map_free_inequality(bset_to_bmap(bset),
1725 n));
1726}
1727
1728int isl_basic_map_drop_inequality(__isl_keep isl_basic_map *bmap, unsigned pos)
1729{
1730 isl_int *t;
1731 if (!bmap)
1732 return -1;
1733 isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
1734
1735 if (pos != bmap->n_ineq - 1) {
1736 t = bmap->ineq[pos];
1737 bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
1738 bmap->ineq[bmap->n_ineq - 1] = t;
1739 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
1740 }
1741 bmap->n_ineq--;
1742 return 0;
1743}
1744
1745int isl_basic_set_drop_inequality(__isl_keep isl_basic_set *bset, unsigned pos)
1746{
1747 return isl_basic_map_drop_inequality(bset_to_bmap(bset), pos);
1748}
1749
1750__isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
1751 isl_int *eq)
1752{
1753 isl_bool empty;
1754 isl_size total;
1755 int k;
1756
1757 empty = isl_basic_map_plain_is_empty(bmap);
1758 if (empty < 0)
1759 return isl_basic_map_free(bmap);
1760 if (empty)
1761 return bmap;
1762
1763 bmap = isl_basic_map_cow(bmap);
1764 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
1765 total = isl_basic_map_dim(bmap, isl_dim_all);
1766 if (total < 0)
1767 return isl_basic_map_free(bmap);
1768 k = isl_basic_map_alloc_equality(bmap);
1769 if (k < 0)
1770 goto error;
1771 isl_seq_cpy(bmap->eq[k], eq, 1 + total);
1772 return bmap;
1773error:
1774 isl_basic_map_free(bmap);
1775 return NULL;
1776}
1777
1778__isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
1779 isl_int *eq)
1780{
1781 return bset_from_bmap(isl_basic_map_add_eq(bset_to_bmap(bset), eq));
1782}
1783
1784__isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
1785 isl_int *ineq)
1786{
1787 isl_size total;
1788 int k;
1789
1790 bmap = isl_basic_map_cow(bmap);
1791 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
1792 total = isl_basic_map_dim(bmap, isl_dim_all);
1793 if (total < 0)
1794 return isl_basic_map_free(bmap);
1795 k = isl_basic_map_alloc_inequality(bmap);
1796 if (k < 0)
1797 goto error;
1798 isl_seq_cpy(bmap->ineq[k], ineq, 1 + total);
1799 return bmap;
1800error:
1801 isl_basic_map_free(bmap);
1802 return NULL;
1803}
1804
1805__isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
1806 isl_int *ineq)
1807{
1808 return bset_from_bmap(isl_basic_map_add_ineq(bset_to_bmap(bset), ineq));
1809}
1810
1811int isl_basic_map_alloc_div(__isl_keep isl_basic_map *bmap)
1812{
1813 isl_size total;
1814
1815 total = isl_basic_map_dim(bmap, isl_dim_all);
1816 if (total < 0)
1817 return -1;
1818 isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
1819 isl_seq_clr(bmap->div[bmap->n_div] + 1 + 1 + total,
1820 bmap->extra - bmap->n_div);
1821 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
1822 return bmap->n_div++;
1823}
1824
1825int isl_basic_set_alloc_div(__isl_keep isl_basic_set *bset)
1826{
1827 return isl_basic_map_alloc_div(bset_to_bmap(bset));
1828}
1829
1830#undef TYPE
1831#define TYPE isl_basic_map
1832#include "check_type_range_templ.c"
1833
1834/* Check that there are "n" dimensions of type "type" starting at "first"
1835 * in "bset".
1836 */
1837isl_stat isl_basic_set_check_range(__isl_keep isl_basic_set *bset,
1838 enum isl_dim_type type, unsigned first, unsigned n)
1839{
1840 return isl_basic_map_check_range(bset_to_bmap(bset),
1841 type, first, n);
1842}
1843
1844/* Insert an extra integer division, prescribed by "div", to "bmap"
1845 * at (integer division) position "pos".
1846 *
1847 * The integer division is first added at the end and then moved
1848 * into the right position.
1849 */
1850__isl_give isl_basic_map *isl_basic_map_insert_div(
1851 __isl_take isl_basic_map *bmap, int pos, __isl_keep isl_vec *div)
1852{
1853 int i, k;
1854 isl_size total;
1855
1856 bmap = isl_basic_map_cow(bmap);
1857 total = isl_basic_map_dim(bmap, isl_dim_all);
1858 if (total < 0 || !div)
1859 return isl_basic_map_free(bmap);
1860
1861 if (div->size != 1 + 1 + total)
1862 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
1863 "unexpected size", return isl_basic_map_free(bmap));
1864 if (isl_basic_map_check_range(bmap, isl_dim_div, pos, 0) < 0)
1865 return isl_basic_map_free(bmap);
1866
1867 bmap = isl_basic_map_extend(bmap, 1, 0, 2);
1868 k = isl_basic_map_alloc_div(bmap);
1869 if (k < 0)
1870 return isl_basic_map_free(bmap);
1871 isl_seq_cpy(bmap->div[k], div->el, div->size);
1872 isl_int_set_si(bmap->div[k][div->size], 0);
1873
1874 for (i = k; i > pos; --i)
1875 bmap = isl_basic_map_swap_div(bmap, i, i - 1);
1876
1877 return bmap;
1878}
1879
1880isl_stat isl_basic_map_free_div(__isl_keep isl_basic_map *bmap, unsigned n)
1881{
1882 if (!bmap)
1883 return isl_stat_error;
1884 isl_assert(bmap->ctx, n <= bmap->n_div, return isl_stat_error);
1885 bmap->n_div -= n;
1886 return isl_stat_ok;
1887}
1888
1889static __isl_give isl_basic_map *add_constraints(
1890 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2,
1891 unsigned i_pos, unsigned o_pos)
1892{
1893 isl_size total, n_param, n_in, n_out, n_div;
1894 unsigned o_in, o_out;
1895 isl_ctx *ctx;
1896 isl_space *space;
1897 struct isl_dim_map *dim_map;
1898
1899 space = isl_basic_map_peek_space(bmap2);
1900 if (!bmap1 || !space)
1901 goto error;
1902
1903 total = isl_basic_map_dim(bmap1, isl_dim_all);
1904 n_param = isl_basic_map_dim(bmap2, isl_dim_param);
1905 n_in = isl_basic_map_dim(bmap2, isl_dim_in);
1906 o_in = isl_basic_map_offset(bmap1, isl_dim_in) - 1 + i_pos;
1907 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
1908 o_out = isl_basic_map_offset(bmap1, isl_dim_out) - 1 + o_pos;
1909 n_div = isl_basic_map_dim(bmap2, isl_dim_div);
1910 if (total < 0 || n_param < 0 || n_in < 0 || n_out < 0 || n_div < 0)
1911 goto error;
1912 ctx = isl_basic_map_get_ctx(bmap1);
1913 dim_map = isl_dim_map_alloc(ctx, total + n_div);
1914 isl_dim_map_dim_range(dim_map, space, isl_dim_param, 0, n_param, 0);
1915 isl_dim_map_dim_range(dim_map, space, isl_dim_in, 0, n_in, o_in);
1916 isl_dim_map_dim_range(dim_map, space, isl_dim_out, 0, n_out, o_out);
1917 isl_dim_map_div(dim_map, bmap2, total);
1918
1919 return isl_basic_map_add_constraints_dim_map(bmap1, bmap2, dim_map);
1920error:
1921 isl_basic_map_free(bmap1);
1922 isl_basic_map_free(bmap2);
1923 return NULL;
1924}
1925
1926__isl_give isl_basic_map *isl_basic_map_extend(__isl_take isl_basic_map *base,
1927 unsigned extra, unsigned n_eq, unsigned n_ineq)
1928{
1929 isl_space *space;
1930 struct isl_basic_map *ext;
1931 unsigned flags;
1932 int dims_ok;
1933
1934 if (!base)
1935 goto error;
1936
1937 dims_ok = base->extra >= base->n_div + extra;
1938
1939 if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
1940 room_for_ineq(base, n_ineq))
1941 return base;
1942
1943 extra += base->extra;
1944 n_eq += base->n_eq;
1945 n_ineq += base->n_ineq;
1946
1947 space = isl_basic_map_get_space(base);
1948 ext = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
1949 if (!ext)
1950 goto error;
1951
1952 if (dims_ok)
1953 ext->sample = isl_vec_copy(base->sample);
1954 flags = base->flags;
1955 ext = add_constraints(ext, base, 0, 0);
1956 if (ext) {
1957 ext->flags = flags;
1958 ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
1959 }
1960
1961 return ext;
1962
1963error:
1964 isl_basic_map_free(base);
1965 return NULL;
1966}
1967
1968__isl_give isl_basic_set *isl_basic_set_extend(__isl_take isl_basic_set *base,
1969 unsigned extra, unsigned n_eq, unsigned n_ineq)
1970{
1971 return bset_from_bmap(isl_basic_map_extend(bset_to_bmap(base),
1972 extra, n_eq, n_ineq));
1973}
1974
1975__isl_give isl_basic_map *isl_basic_map_extend_constraints(
1976 __isl_take isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
1977{
1978 return isl_basic_map_extend(base, 0, n_eq, n_ineq);
1979}
1980
1981__isl_give isl_basic_set *isl_basic_set_extend_constraints(
1982 __isl_take isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
1983{
1984 isl_basic_map *bmap = bset_to_bmap(base);
1985 bmap = isl_basic_map_extend_constraints(bmap, n_eq, n_ineq);
1986 return bset_from_bmap(bmap);
1987}
1988
1989__isl_give isl_basic_set *isl_basic_set_cow(__isl_take isl_basic_set *bset)
1990{
1991 return bset_from_bmap(isl_basic_map_cow(bset_to_bmap(bset)));
1992}
1993
1994__isl_give isl_basic_map *isl_basic_map_cow(__isl_take isl_basic_map *bmap)
1995{
1996 if (!bmap)
1997 return NULL;
1998
1999 if (bmap->ref > 1) {
2000 bmap->ref--;
2001 bmap = isl_basic_map_dup(bmap);
2002 }
2003 if (bmap) {
2004 ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
2005 ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
2006 }
2007 return bmap;
2008}
2009
2010/* Clear all cached information in "map", either because it is about
2011 * to be modified or because it is being freed.
2012 * Always return the same pointer that is passed in.
2013 * This is needed for the use in isl_map_free.
2014 */
2015static __isl_give isl_map *clear_caches(__isl_take isl_map *map)
2016{
2017 isl_basic_map_free(map->cached_simple_hull[0]);
2018 isl_basic_map_free(map->cached_simple_hull[1]);
2019 map->cached_simple_hull[0] = NULL;
2020 map->cached_simple_hull[1] = NULL;
2021 return map;
2022}
2023
2024__isl_give isl_set *isl_set_cow(__isl_take isl_set *set)
2025{
2026 return isl_map_cow(set);
2027}
2028
2029/* Return an isl_map that is equal to "map" and that has only
2030 * a single reference.
2031 *
2032 * If the original input already has only one reference, then
2033 * simply return it, but clear all cached information, since
2034 * it may be rendered invalid by the operations that will be
2035 * performed on the result.
2036 *
2037 * Otherwise, create a duplicate (without any cached information).
2038 */
2039__isl_give isl_map *isl_map_cow(__isl_take isl_map *map)
2040{
2041 if (!map)
2042 return NULL;
2043
2044 if (map->ref == 1)
2045 return clear_caches(map);
2046 map->ref--;
2047 return isl_map_dup(map);
2048}
2049
2050static void swap_vars(struct isl_blk blk, isl_int *a,
2051 unsigned a_len, unsigned b_len)
2052{
2053 isl_seq_cpy(blk.data, a+a_len, b_len);
2054 isl_seq_cpy(blk.data+b_len, a, a_len);
2055 isl_seq_cpy(a, blk.data, b_len+a_len);
2056}
2057
2058static __isl_give isl_basic_map *isl_basic_map_swap_vars(
2059 __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
2060{
2061 int i;
2062 struct isl_blk blk;
2063
2064 if (isl_basic_map_check_range(bmap, isl_dim_all, pos - 1, n1 + n2) < 0)
2065 goto error;
2066
2067 if (n1 == 0 || n2 == 0)
2068 return bmap;
2069
2070 bmap = isl_basic_map_cow(bmap);
2071 if (!bmap)
2072 return NULL;
2073
2074 blk = isl_blk_alloc(bmap->ctx, n1 + n2);
2075 if (isl_blk_is_error(blk))
2076 goto error;
2077
2078 for (i = 0; i < bmap->n_eq; ++i)
2079 swap_vars(blk,
2080 bmap->eq[i] + pos, n1, n2);
2081
2082 for (i = 0; i < bmap->n_ineq; ++i)
2083 swap_vars(blk,
2084 bmap->ineq[i] + pos, n1, n2);
2085
2086 for (i = 0; i < bmap->n_div; ++i)
2087 swap_vars(blk,
2088 bmap->div[i]+1 + pos, n1, n2);
2089
2090 isl_blk_free(bmap->ctx, blk);
2091
2092 ISL_F_CLR(bmap, ISL_BASIC_SET_SORTED);
2093 bmap = isl_basic_map_gauss(bmap, NULL);
2094 return isl_basic_map_finalize(bmap);
2095error:
2096 isl_basic_map_free(bmap);
2097 return NULL;
2098}
2099
2100/* The given basic map has turned out to be empty.
2101 * Explicitly mark it as such and change the representation
2102 * to a canonical representation of the empty basic map.
2103 * Since the basic map has conflicting constraints,
2104 * it must have at least one constraint, except perhaps
2105 * if it was already explicitly marked as being empty.
2106 * Do nothing in the latter case.
2107 */
2108__isl_give isl_basic_map *isl_basic_map_set_to_empty(
2109 __isl_take isl_basic_map *bmap)
2110{
2111 int i = 0;
2112 isl_bool empty;
2113 isl_size total;
2114
2115 empty = isl_basic_map_plain_is_empty(bmap);
2116 if (empty < 0)
2117 return isl_basic_map_free(bmap);
2118 if (empty)
2119 return bmap;
2120 total = isl_basic_map_dim(bmap, isl_dim_all);
2121 if (total < 0)
2122 return isl_basic_map_free(bmap);
2123 if (isl_basic_map_free_div(bmap, bmap->n_div) < 0)
2124 return isl_basic_map_free(bmap);
2125 bmap = isl_basic_map_free_inequality(bmap, bmap->n_ineq);
2126 if (!bmap)
2127 return NULL;
2128 if (bmap->n_eq > 0) {
2129 bmap = isl_basic_map_free_equality(bmap, bmap->n_eq - 1);
2130 if (!bmap)
2131 return NULL;
2132 } else {
2133 i = isl_basic_map_alloc_equality(bmap);
2134 if (i < 0)
2135 goto error;
2136 }
2137 isl_int_set_si(bmap->eq[i][0], 1);
2138 isl_seq_clr(bmap->eq[i]+1, total);
2139 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
2140 isl_vec_free(bmap->sample);
2141 bmap->sample = NULL;
2142 return isl_basic_map_finalize(bmap);
2143error:
2144 isl_basic_map_free(bmap);
2145 return NULL;
2146}
2147
2148__isl_give isl_basic_set *isl_basic_set_set_to_empty(
2149 __isl_take isl_basic_set *bset)
2150{
2151 return bset_from_bmap(isl_basic_map_set_to_empty(bset_to_bmap(bset)));
2152}
2153
2154__isl_give isl_basic_map *isl_basic_map_set_rational(
2155 __isl_take isl_basic_map *bmap)
2156{
2157 if (!bmap)
2158 return NULL;
2159
2160 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
2161 return bmap;
2162
2163 bmap = isl_basic_map_cow(bmap);
2164 if (!bmap)
2165 return NULL;
2166
2167 ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
2168
2169 return isl_basic_map_finalize(bmap);
2170}
2171
2172__isl_give isl_basic_set *isl_basic_set_set_rational(
2173 __isl_take isl_basic_set *bset)
2174{
2175 return isl_basic_map_set_rational(bset);
2176}
2177
2178__isl_give isl_basic_set *isl_basic_set_set_integral(
2179 __isl_take isl_basic_set *bset)
2180{
2181 if (!bset)
2182 return NULL;
2183
2184 if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
2185 return bset;
2186
2187 bset = isl_basic_set_cow(bset);
2188 if (!bset)
2189 return NULL;
2190
2191 ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
2192
2193 return isl_basic_set_finalize(bset);
2194}
2195
2196__isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map)
2197{
2198 int i;
2199
2200 map = isl_map_cow(map);
2201 if (!map)
2202 return NULL;
2203 for (i = 0; i < map->n; ++i) {
2204 map->p[i] = isl_basic_map_set_rational(map->p[i]);
2205 if (!map->p[i])
2206 goto error;
2207 }
2208 return map;
2209error:
2210 isl_map_free(map);
2211 return NULL;
2212}
2213
2214__isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
2215{
2216 return isl_map_set_rational(set);
2217}
2218
2219/* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
2220 * of "bmap").
2221 */
2222static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
2223{
2224 isl_int *t = bmap->div[a];
2225 bmap->div[a] = bmap->div[b];
2226 bmap->div[b] = t;
2227}
2228
2229/* Swap divs "a" and "b" in "bmap" and adjust the constraints and
2230 * div definitions accordingly.
2231 */
2232__isl_give isl_basic_map *isl_basic_map_swap_div(__isl_take isl_basic_map *bmap,
2233 int a, int b)
2234{
2235 int i;
2236 isl_size off;
2237
2238 off = isl_basic_map_var_offset(bmap, isl_dim_div);
2239 if (off < 0)
2240 return isl_basic_map_free(bmap);
2241
2242 swap_div(bmap, a, b);
2243
2244 for (i = 0; i < bmap->n_eq; ++i)
2245 isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
2246
2247 for (i = 0; i < bmap->n_ineq; ++i)
2248 isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
2249
2250 for (i = 0; i < bmap->n_div; ++i)
2251 isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
2252 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2253
2254 return bmap;
2255}
2256
2257static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
2258{
2259 isl_seq_cpy(c, c + n, rem);
2260 isl_seq_clr(c + rem, n);
2261}
2262
2263/* Drop n dimensions starting at first.
2264 *
2265 * In principle, this frees up some extra variables as the number
2266 * of columns remains constant, but we would have to extend
2267 * the div array too as the number of rows in this array is assumed
2268 * to be equal to extra.
2269 */
2270__isl_give isl_basic_set *isl_basic_set_drop_dims(
2271 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
2272{
2273 return isl_basic_map_drop(bset_to_bmap(bset), isl_dim_set, first, n);
2274}
2275
2276/* Move "n" divs starting at "first" to the end of the list of divs.
2277 */
2278static __isl_give isl_basic_map *move_divs_last(__isl_take isl_basic_map *bmap,
2279 unsigned first, unsigned n)
2280{
2281 isl_int **div;
2282 int i;
2283
2284 if (first + n == bmap->n_div)
2285 return bmap;
2286
2287 div = isl_alloc_array(bmap->ctx, isl_int *, n);
2288 if (!div)
2289 goto error;
2290 for (i = 0; i < n; ++i)
2291 div[i] = bmap->div[first + i];
2292 for (i = 0; i < bmap->n_div - first - n; ++i)
2293 bmap->div[first + i] = bmap->div[first + n + i];
2294 for (i = 0; i < n; ++i)
2295 bmap->div[bmap->n_div - n + i] = div[i];
2296 free(div);
2297 return bmap;
2298error:
2299 isl_basic_map_free(bmap);
2300 return NULL;
2301}
2302
2303#undef TYPE
2304#define TYPE isl_map
2305static
2306#include "check_type_range_templ.c"
2307
2308/* Check that there are "n" dimensions of type "type" starting at "first"
2309 * in "set".
2310 */
2311isl_stat isl_set_check_range(__isl_keep isl_set *set,
2312 enum isl_dim_type type, unsigned first, unsigned n)
2313{
2314 return isl_map_check_range(set_to_map(set), type, first, n);
2315}
2316
2317/* Drop "n" dimensions of type "type" starting at "first".
2318 * Perform the core computation, without cowing or
2319 * simplifying and finalizing the result.
2320 *
2321 * In principle, this frees up some extra variables as the number
2322 * of columns remains constant, but we would have to extend
2323 * the div array too as the number of rows in this array is assumed
2324 * to be equal to extra.
2325 */
2326__isl_give isl_basic_map *isl_basic_map_drop_core(
2327 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2328 unsigned first, unsigned n)
2329{
2330 int i;
2331 unsigned offset;
2332 unsigned left;
2333 isl_size total;
2334
2335 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2336 return isl_basic_map_free(bmap);
2337
2338 total = isl_basic_map_dim(bmap, isl_dim_all);
2339 if (total < 0)
2340 return isl_basic_map_free(bmap);
2341
2342 offset = isl_basic_map_offset(bmap, type) + first;
2343 left = total - (offset - 1) - n;
2344 for (i = 0; i < bmap->n_eq; ++i)
2345 constraint_drop_vars(bmap->eq[i]+offset, n, left);
2346
2347 for (i = 0; i < bmap->n_ineq; ++i)
2348 constraint_drop_vars(bmap->ineq[i]+offset, n, left);
2349
2350 for (i = 0; i < bmap->n_div; ++i)
2351 constraint_drop_vars(bmap->div[i]+1+offset, n, left);
2352
2353 if (type == isl_dim_div) {
2354 bmap = move_divs_last(bmap, first, n);
2355 if (!bmap)
2356 return NULL;
2357 if (isl_basic_map_free_div(bmap, n) < 0)
2358 return isl_basic_map_free(bmap);
2359 } else
2360 bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
2361 if (!bmap->dim)
2362 return isl_basic_map_free(bmap);
2363
2364 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
2365 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
2366 return bmap;
2367}
2368
2369/* Drop "n" dimensions of type "type" starting at "first".
2370 *
2371 * In principle, this frees up some extra variables as the number
2372 * of columns remains constant, but we would have to extend
2373 * the div array too as the number of rows in this array is assumed
2374 * to be equal to extra.
2375 */
2376__isl_give isl_basic_map *isl_basic_map_drop(__isl_take isl_basic_map *bmap,
2377 enum isl_dim_type type, unsigned first, unsigned n)
2378{
2379 if (!bmap)
2380 return NULL;
2381 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2382 return bmap;
2383
2384 bmap = isl_basic_map_cow(bmap);
2385 if (!bmap)
2386 return NULL;
2387
2388 bmap = isl_basic_map_drop_core(bmap, type, first, n);
2389
2390 bmap = isl_basic_map_simplify(bmap);
2391 return isl_basic_map_finalize(bmap);
2392}
2393
2394__isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
2395 enum isl_dim_type type, unsigned first, unsigned n)
2396{
2397 return bset_from_bmap(isl_basic_map_drop(bset_to_bmap(bset),
2398 type, first, n));
2399}
2400
2401/* No longer consider "map" to be normalized.
2402 */
2403static __isl_give isl_map *isl_map_unmark_normalized(__isl_take isl_map *map)
2404{
2405 if (!map)
2406 return NULL;
2407 ISL_F_CLR(map, ISL_MAP_NORMALIZED);
2408 return map;
2409}
2410
2411__isl_give isl_map *isl_map_drop(__isl_take isl_map *map,
2412 enum isl_dim_type type, unsigned first, unsigned n)
2413{
2414 int i;
2415 isl_space *space;
2416
2417 if (isl_map_check_range(map, type, first, n) < 0)
2418 return isl_map_free(map);
2419
2420 if (n == 0 && !isl_space_is_named_or_nested(map->dim, type))
2421 return map;
2422 map = isl_map_cow(map);
2423 if (!map)
2424 goto error;
2425
2426 for (i = 0; i < map->n; ++i) {
2427 map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
2428 if (!map->p[i])
2429 goto error;
2430 }
2431 map = isl_map_unmark_normalized(map);
2432
2433 space = isl_map_take_space(map);
2434 space = isl_space_drop_dims(space, type, first, n);
2435 map = isl_map_restore_space(map, space);
2436
2437 return map;
2438error:
2439 isl_map_free(map);
2440 return NULL;
2441}
2442
2443__isl_give isl_set *isl_set_drop(__isl_take isl_set *set,
2444 enum isl_dim_type type, unsigned first, unsigned n)
2445{
2446 return set_from_map(isl_map_drop(set_to_map(set), type, first, n));
2447}
2448
2449/* Drop the integer division at position "div", which is assumed
2450 * not to appear in any of the constraints or
2451 * in any of the other integer divisions.
2452 *
2453 * Since the integer division is redundant, there is no need to cow.
2454 */
2455__isl_give isl_basic_map *isl_basic_map_drop_div(
2456 __isl_take isl_basic_map *bmap, unsigned div)
2457{
2458 return isl_basic_map_drop_core(bmap, isl_dim_div, div, 1);
2459}
2460
2461/* Eliminate the specified n dimensions starting at first from the
2462 * constraints, without removing the dimensions from the space.
2463 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2464 */
2465__isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
2466 enum isl_dim_type type, unsigned first, unsigned n)
2467{
2468 int i;
2469
2470 if (n == 0)
2471 return map;
2472
2473 if (isl_map_check_range(map, type, first, n) < 0)
2474 return isl_map_free(map);
2475
2476 map = isl_map_cow(map);
2477 if (!map)
2478 return NULL;
2479
2480 for (i = 0; i < map->n; ++i) {
2481 map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
2482 if (!map->p[i])
2483 goto error;
2484 }
2485 return map;
2486error:
2487 isl_map_free(map);
2488 return NULL;
2489}
2490
2491/* Eliminate the specified n dimensions starting at first from the
2492 * constraints, without removing the dimensions from the space.
2493 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2494 */
2495__isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
2496 enum isl_dim_type type, unsigned first, unsigned n)
2497{
2498 return set_from_map(isl_map_eliminate(set_to_map(set), type, first, n));
2499}
2500
2501/* Eliminate the specified n dimensions starting at first from the
2502 * constraints, without removing the dimensions from the space.
2503 * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
2504 */
2505__isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
2506 unsigned first, unsigned n)
2507{
2508 return isl_set_eliminate(set, isl_dim_set, first, n);
2509}
2510
2511__isl_give isl_basic_map *isl_basic_map_remove_divs(
2512 __isl_take isl_basic_map *bmap)
2513{
2514 isl_size v_div;
2515
2516 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2517 if (v_div < 0)
2518 return isl_basic_map_free(bmap);
2519 bmap = isl_basic_map_eliminate_vars(bmap, v_div, bmap->n_div);
2520 if (!bmap)
2521 return NULL;
2522 bmap->n_div = 0;
2523 return isl_basic_map_finalize(bmap);
2524}
2525
2526__isl_give isl_basic_set *isl_basic_set_remove_divs(
2527 __isl_take isl_basic_set *bset)
2528{
2529 return bset_from_bmap(isl_basic_map_remove_divs(bset_to_bmap(bset)));
2530}
2531
2532__isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
2533{
2534 int i;
2535
2536 if (!map)
2537 return NULL;
2538 if (map->n == 0)
2539 return map;
2540
2541 map = isl_map_cow(map);
2542 if (!map)
2543 return NULL;
2544
2545 for (i = 0; i < map->n; ++i) {
2546 map->p[i] = isl_basic_map_remove_divs(map->p[i]);
2547 if (!map->p[i])
2548 goto error;
2549 }
2550 return map;
2551error:
2552 isl_map_free(map);
2553 return NULL;
2554}
2555
2556__isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
2557{
2558 return isl_map_remove_divs(set);
2559}
2560
2561__isl_give isl_basic_map *isl_basic_map_remove_dims(
2562 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
2563 unsigned first, unsigned n)
2564{
2565 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2566 return isl_basic_map_free(bmap);
2567 if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
2568 return bmap;
2569 bmap = isl_basic_map_eliminate_vars(bmap,
2570 isl_basic_map_offset(bmap, type) - 1 + first, n);
2571 if (!bmap)
2572 return bmap;
2573 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
2574 return bmap;
2575 bmap = isl_basic_map_drop(bmap, type, first, n);
2576 return bmap;
2577}
2578
2579/* Return true if the definition of the given div (recursively) involves
2580 * any of the given variables.
2581 */
2582static isl_bool div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
2583 unsigned first, unsigned n)
2584{
2585 int i;
2586 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
2587
2588 if (isl_int_is_zero(bmap->div[div][0]))
2589 return isl_bool_false;
2590 if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
2591 return isl_bool_true;
2592
2593 for (i = bmap->n_div - 1; i >= 0; --i) {
2594 isl_bool involves;
2595
2596 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
2597 continue;
2598 involves = div_involves_vars(bmap, i, first, n);
2599 if (involves < 0 || involves)
2600 return involves;
2601 }
2602
2603 return isl_bool_false;
2604}
2605
2606/* Try and add a lower and/or upper bound on "div" to "bmap"
2607 * based on inequality "i".
2608 * "total" is the total number of variables (excluding the divs).
2609 * "v" is a temporary object that can be used during the calculations.
2610 * If "lb" is set, then a lower bound should be constructed.
2611 * If "ub" is set, then an upper bound should be constructed.
2612 *
2613 * The calling function has already checked that the inequality does not
2614 * reference "div", but we still need to check that the inequality is
2615 * of the right form. We'll consider the case where we want to construct
2616 * a lower bound. The construction of upper bounds is similar.
2617 *
2618 * Let "div" be of the form
2619 *
2620 * q = floor((a + f(x))/d)
2621 *
2622 * We essentially check if constraint "i" is of the form
2623 *
2624 * b + f(x) >= 0
2625 *
2626 * so that we can use it to derive a lower bound on "div".
2627 * However, we allow a slightly more general form
2628 *
2629 * b + g(x) >= 0
2630 *
2631 * with the condition that the coefficients of g(x) - f(x) are all
2632 * divisible by d.
2633 * Rewriting this constraint as
2634 *
2635 * 0 >= -b - g(x)
2636 *
2637 * adding a + f(x) to both sides and dividing by d, we obtain
2638 *
2639 * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
2640 *
2641 * Taking the floor on both sides, we obtain
2642 *
2643 * q >= floor((a-b)/d) + (f(x)-g(x))/d
2644 *
2645 * or
2646 *
2647 * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
2648 *
2649 * In the case of an upper bound, we construct the constraint
2650 *
2651 * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
2652 *
2653 */
2654static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
2655 __isl_take isl_basic_map *bmap, int div, int i,
2656 unsigned total, isl_int v, int lb, int ub)
2657{
2658 int j;
2659
2660 for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
2661 if (lb) {
2662 isl_int_sub(v, bmap->ineq[i][1 + j],
2663 bmap->div[div][1 + 1 + j]);
2664 lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
2665 }
2666 if (ub) {
2667 isl_int_add(v, bmap->ineq[i][1 + j],
2668 bmap->div[div][1 + 1 + j]);
2669 ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
2670 }
2671 }
2672 if (!lb && !ub)
2673 return bmap;
2674
2675 bmap = isl_basic_map_cow(bmap);
2676 bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
2677 if (lb) {
2678 int k = isl_basic_map_alloc_inequality(bmap);
2679 if (k < 0)
2680 goto error;
2681 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2682 isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
2683 bmap->div[div][1 + j]);
2684 isl_int_cdiv_q(bmap->ineq[k][j],
2685 bmap->ineq[k][j], bmap->div[div][0]);
2686 }
2687 isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
2688 }
2689 if (ub) {
2690 int k = isl_basic_map_alloc_inequality(bmap);
2691 if (k < 0)
2692 goto error;
2693 for (j = 0; j < 1 + total + bmap->n_div; ++j) {
2694 isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
2695 bmap->div[div][1 + j]);
2696 isl_int_fdiv_q(bmap->ineq[k][j],
2697 bmap->ineq[k][j], bmap->div[div][0]);
2698 }
2699 isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
2700 }
2701
2702 return bmap;
2703error:
2704 isl_basic_map_free(bmap);
2705 return NULL;
2706}
2707
2708/* This function is called right before "div" is eliminated from "bmap"
2709 * using Fourier-Motzkin.
2710 * Look through the constraints of "bmap" for constraints on the argument
2711 * of the integer division and use them to construct constraints on the
2712 * integer division itself. These constraints can then be combined
2713 * during the Fourier-Motzkin elimination.
2714 * Note that it is only useful to introduce lower bounds on "div"
2715 * if "bmap" already contains upper bounds on "div" as the newly
2716 * introduce lower bounds can then be combined with the pre-existing
2717 * upper bounds. Similarly for upper bounds.
2718 * We therefore first check if "bmap" contains any lower and/or upper bounds
2719 * on "div".
2720 *
2721 * It is interesting to note that the introduction of these constraints
2722 * can indeed lead to more accurate results, even when compared to
2723 * deriving constraints on the argument of "div" from constraints on "div".
2724 * Consider, for example, the set
2725 *
2726 * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
2727 *
2728 * The second constraint can be rewritten as
2729 *
2730 * 2 * [(-i-2j+3)/4] + k >= 0
2731 *
2732 * from which we can derive
2733 *
2734 * -i - 2j + 3 >= -2k
2735 *
2736 * or
2737 *
2738 * i + 2j <= 3 + 2k
2739 *
2740 * Combined with the first constraint, we obtain
2741 *
2742 * -3 <= 3 + 2k or k >= -3
2743 *
2744 * If, on the other hand we derive a constraint on [(i+2j)/4] from
2745 * the first constraint, we obtain
2746 *
2747 * [(i + 2j)/4] >= [-3/4] = -1
2748 *
2749 * Combining this constraint with the second constraint, we obtain
2750 *
2751 * k >= -2
2752 */
2753static __isl_give isl_basic_map *insert_bounds_on_div(
2754 __isl_take isl_basic_map *bmap, int div)
2755{
2756 int i;
2757 int check_lb, check_ub;
2758 isl_int v;
2759 isl_size v_div;
2760
2761 if (!bmap)
2762 return NULL;
2763
2764 if (isl_int_is_zero(bmap->div[div][0]))
2765 return bmap;
2766
2767 v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
2768 if (v_div < 0)
2769 return isl_basic_map_free(bmap);
2770
2771 check_lb = 0;
2772 check_ub = 0;
2773 for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
2774 int s = isl_int_sgn(bmap->ineq[i][1 + v_div + div]);
2775 if (s > 0)
2776 check_ub = 1;
2777 if (s < 0)
2778 check_lb = 1;
2779 }
2780
2781 if (!check_lb && !check_ub)
2782 return bmap;
2783
2784 isl_int_init(v);
2785
2786 for (i = 0; bmap && i < bmap->n_ineq; ++i) {
2787 if (!isl_int_is_zero(bmap->ineq[i][1 + v_div + div]))
2788 continue;
2789
2790 bmap = insert_bounds_on_div_from_ineq(bmap, div, i, v_div, v,
2791 check_lb, check_ub);
2792 }
2793
2794 isl_int_clear(v);
2795
2796 return bmap;
2797}
2798
2799/* Remove all divs (recursively) involving any of the given dimensions
2800 * in their definitions.
2801 */
2802__isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
2803 __isl_take isl_basic_map *bmap,
2804 enum isl_dim_type type, unsigned first, unsigned n)
2805{
2806 int i;
2807
2808 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2809 return isl_basic_map_free(bmap);
2810 first += isl_basic_map_offset(bmap, type);
2811
2812 for (i = bmap->n_div - 1; i >= 0; --i) {
2813 isl_bool involves;
2814
2815 involves = div_involves_vars(bmap, i, first, n);
2816 if (involves < 0)
2817 return isl_basic_map_free(bmap);
2818 if (!involves)
2819 continue;
2820 bmap = insert_bounds_on_div(bmap, i);
2821 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
2822 if (!bmap)
2823 return NULL;
2824 i = bmap->n_div;
2825 }
2826
2827 return bmap;
2828}
2829
2830__isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
2831 __isl_take isl_basic_set *bset,
2832 enum isl_dim_type type, unsigned first, unsigned n)
2833{
2834 return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
2835}
2836
2837__isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
2838 enum isl_dim_type type, unsigned first, unsigned n)
2839{
2840 int i;
2841
2842 if (!map)
2843 return NULL;
2844 if (map->n == 0)
2845 return map;
2846
2847 map = isl_map_cow(map);
2848 if (!map)
2849 return NULL;
2850
2851 for (i = 0; i < map->n; ++i) {
2852 map->p[i] = isl_basic_map_remove_divs_involving_dims(map->p[i],
2853 type, first, n);
2854 if (!map->p[i])
2855 goto error;
2856 }
2857 return map;
2858error:
2859 isl_map_free(map);
2860 return NULL;
2861}
2862
2863__isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
2864 enum isl_dim_type type, unsigned first, unsigned n)
2865{
2866 return set_from_map(isl_map_remove_divs_involving_dims(set_to_map(set),
2867 type, first, n));
2868}
2869
2870/* Does the description of "bmap" depend on the specified dimensions?
2871 * We also check whether the dimensions appear in any of the div definitions.
2872 * In principle there is no need for this check. If the dimensions appear
2873 * in a div definition, they also appear in the defining constraints of that
2874 * div.
2875 */
2876isl_bool isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
2877 enum isl_dim_type type, unsigned first, unsigned n)
2878{
2879 int i;
2880
2881 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
2882 return isl_bool_error;
2883
2884 first += isl_basic_map_offset(bmap, type);
2885 for (i = 0; i < bmap->n_eq; ++i)
2886 if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
2887 return isl_bool_true;
2888 for (i = 0; i < bmap->n_ineq; ++i)
2889 if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
2890 return isl_bool_true;
2891 for (i = 0; i < bmap->n_div; ++i) {
2892 if (isl_int_is_zero(bmap->div[i][0]))
2893 continue;
2894 if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
2895 return isl_bool_true;
2896 }
2897
2898 return isl_bool_false;
2899}
2900
2901isl_bool isl_map_involves_dims(__isl_keep isl_map *map,
2902 enum isl_dim_type type, unsigned first, unsigned n)
2903{
2904 int i;
2905
2906 if (isl_map_check_range(map, type, first, n) < 0)
2907 return isl_bool_error;
2908
2909 for (i = 0; i < map->n; ++i) {
2910 isl_bool involves = isl_basic_map_involves_dims(map->p[i],
2911 type, first, n);
2912 if (involves < 0 || involves)
2913 return involves;
2914 }
2915
2916 return isl_bool_false;
2917}
2918
2919isl_bool isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
2920 enum isl_dim_type type, unsigned first, unsigned n)
2921{
2922 return isl_basic_map_involves_dims(bset, type, first, n);
2923}
2924
2925isl_bool isl_set_involves_dims(__isl_keep isl_set *set,
2926 enum isl_dim_type type, unsigned first, unsigned n)
2927{
2928 return isl_map_involves_dims(set, type, first, n);
2929}
2930
2931/* Does "bset" involve any local variables, i.e., integer divisions?
2932 */
2933static isl_bool isl_basic_set_involves_locals(__isl_keep isl_basic_set *bset)
2934{
2935 isl_size n;
2936
2937 n = isl_basic_set_dim(bset, isl_dim_div);
2938 if (n < 0)
2939 return isl_bool_error;
2940 return isl_bool_ok(n > 0);
2941}
2942
2943/* isl_set_every_basic_set callback that checks whether "bset"
2944 * is free of local variables.
2945 */
2946static isl_bool basic_set_no_locals(__isl_keep isl_basic_set *bset, void *user)
2947{
2948 return isl_bool_not(isl_basic_set_involves_locals(bset));
2949}
2950
2951/* Does "set" involve any local variables, i.e., integer divisions?
2952 */
2953isl_bool isl_set_involves_locals(__isl_keep isl_set *set)
2954{
2955 isl_bool no_locals;
2956
2957 no_locals = isl_set_every_basic_set(set, &basic_set_no_locals, NULL);
2958 return isl_bool_not(no_locals);
2959}
2960
2961/* Drop all constraints in bmap that involve any of the dimensions
2962 * first to first+n-1.
2963 * This function only performs the actual removal of constraints.
2964 *
2965 * This function should not call finalize since it is used by
2966 * remove_redundant_divs, which in turn is called by isl_basic_map_finalize.
2967 */
2968__isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
2969 __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
2970{
2971 int i;
2972
2973 if (n == 0)
2974 return bmap;
2975
2976 bmap = isl_basic_map_cow(bmap);
2977
2978 if (!bmap)
2979 return NULL;
2980
2981 for (i = bmap->n_eq - 1; i >= 0; --i) {
2982 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
2983 continue;
2984 if (isl_basic_map_drop_equality(bmap, i) < 0)
2985 return isl_basic_map_free(bmap);
2986 }
2987
2988 for (i = bmap->n_ineq - 1; i >= 0; --i) {
2989 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
2990 continue;
2991 if (isl_basic_map_drop_inequality(bmap, i) < 0)
2992 return isl_basic_map_free(bmap);
2993 }
2994
2995 return bmap;
2996}
2997
2998/* Drop all constraints in bset that involve any of the dimensions
2999 * first to first+n-1.
3000 * This function only performs the actual removal of constraints.
3001 */
3002__isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
3003 __isl_take isl_basic_set *bset, unsigned first, unsigned n)
3004{
3005 return isl_basic_map_drop_constraints_involving(bset, first, n);
3006}
3007
3008/* Drop all constraints in bmap that do not involve any of the dimensions
3009 * first to first + n - 1 of the given type.
3010 */
3011__isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
3012 __isl_take isl_basic_map *bmap,
3013 enum isl_dim_type type, unsigned first, unsigned n)
3014{
3015 int i;
3016
3017 if (n == 0) {
3018 isl_space *space = isl_basic_map_get_space(bmap);
3019 isl_basic_map_free(bmap);
3020 return isl_basic_map_universe(space);
3021 }
3022 bmap = isl_basic_map_cow(bmap);
3023 if (!bmap)
3024 return NULL;
3025
3026 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3027 return isl_basic_map_free(bmap);
3028
3029 first += isl_basic_map_offset(bmap, type) - 1;
3030
3031 for (i = bmap->n_eq - 1; i >= 0; --i) {
3032 if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
3033 continue;
3034 if (isl_basic_map_drop_equality(bmap, i) < 0)
3035 return isl_basic_map_free(bmap);
3036 }
3037
3038 for (i = bmap->n_ineq - 1; i >= 0; --i) {
3039 if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
3040 continue;
3041 if (isl_basic_map_drop_inequality(bmap, i) < 0)
3042 return isl_basic_map_free(bmap);
3043 }
3044
3045 bmap = isl_basic_map_add_known_div_constraints(bmap);
3046 return bmap;
3047}
3048
3049/* Drop all constraints in bset that do not involve any of the dimensions
3050 * first to first + n - 1 of the given type.
3051 */
3052__isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
3053 __isl_take isl_basic_set *bset,
3054 enum isl_dim_type type, unsigned first, unsigned n)
3055{
3056 return isl_basic_map_drop_constraints_not_involving_dims(bset,
3057 type, first, n);
3058}
3059
3060/* Drop all constraints in bmap that involve any of the dimensions
3061 * first to first + n - 1 of the given type.
3062 */
3063__isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
3064 __isl_take isl_basic_map *bmap,
3065 enum isl_dim_type type, unsigned first, unsigned n)
3066{
3067 if (!bmap)
3068 return NULL;
3069 if (n == 0)
3070 return bmap;
3071
3072 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
3073 return isl_basic_map_free(bmap);
3074
3075 bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
3076 first += isl_basic_map_offset(bmap, type) - 1;
3077 bmap = isl_basic_map_drop_constraints_involving(bmap, first, n);
3078 bmap = isl_basic_map_add_known_div_constraints(bmap);
3079 return bmap;
3080}
3081
3082/* Drop all constraints in bset that involve any of the dimensions
3083 * first to first + n - 1 of the given type.
3084 */
3085__isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
3086 __isl_take isl_basic_set *bset,
3087 enum isl_dim_type type, unsigned first, unsigned n)
3088{
3089 return isl_basic_map_drop_constraints_involving_dims(bset,
3090 type, first, n);
3091}
3092
3093/* Drop constraints from "map" by applying "drop" to each basic map.
3094 */
3095static __isl_give isl_map *drop_constraints(__isl_take isl_map *map,
3096 enum isl_dim_type type, unsigned first, unsigned n,
3097 __isl_give isl_basic_map *(*drop)(__isl_take isl_basic_map *bmap,
3098 enum isl_dim_type type, unsigned first, unsigned n))
3099{
3100 int i;
3101
3102 if (isl_map_check_range(map, type, first, n) < 0)
3103 return isl_map_free(map);
3104
3105 map = isl_map_cow(map);
3106 if (!map)
3107 return NULL;
3108
3109 for (i = 0; i < map->n; ++i) {
3110 map->p[i] = drop(map->p[i], type, first, n);
3111 if (!map->p[i])
3112 return isl_map_free(map);
3113 }
3114
3115 if (map->n > 1)
3116 ISL_F_CLR(map, ISL_MAP_DISJOINT);
3117
3118 return map;
3119}
3120
3121/* Drop all constraints in map that involve any of the dimensions
3122 * first to first + n - 1 of the given type.
3123 */
3124__isl_give isl_map *isl_map_drop_constraints_involving_dims(
3125 __isl_take isl_map *map,
3126 enum isl_dim_type type, unsigned first, unsigned n)
3127{
3128 if (n == 0)
3129 return map;
3130 return drop_constraints(map, type, first, n,
3131 &isl_basic_map_drop_constraints_involving_dims);
3132}
3133
3134/* Drop all constraints in "map" that do not involve any of the dimensions
3135 * first to first + n - 1 of the given type.
3136 */
3137__isl_give isl_map *isl_map_drop_constraints_not_involving_dims(
3138 __isl_take isl_map *map,
3139 enum isl_dim_type type, unsigned first, unsigned n)
3140{
3141 if (n == 0) {
3142 isl_space *space = isl_map_get_space(map);
3143 isl_map_free(map);
3144 return isl_map_universe(space);
3145 }
3146 return drop_constraints(map, type, first, n,
3147 &isl_basic_map_drop_constraints_not_involving_dims);
3148}
3149
3150/* Drop all constraints in set that involve any of the dimensions
3151 * first to first + n - 1 of the given type.
3152 */
3153__isl_give isl_set *isl_set_drop_constraints_involving_dims(
3154 __isl_take isl_set *set,
3155 enum isl_dim_type type, unsigned first, unsigned n)
3156{
3157 return isl_map_drop_constraints_involving_dims(set, type, first, n);
3158}
3159
3160/* Drop all constraints in "set" that do not involve any of the dimensions
3161 * first to first + n - 1 of the given type.
3162 */
3163__isl_give isl_set *isl_set_drop_constraints_not_involving_dims(
3164 __isl_take isl_set *set,
3165 enum isl_dim_type type, unsigned first, unsigned n)
3166{
3167 return isl_map_drop_constraints_not_involving_dims(set, type, first, n);
3168}
3169
3170/* Does local variable "div" of "bmap" have a complete explicit representation?
3171 * Having a complete explicit representation requires not only
3172 * an explicit representation, but also that all local variables
3173 * that appear in this explicit representation in turn have
3174 * a complete explicit representation.
3175 */
3176isl_bool isl_basic_map_div_is_known(__isl_keep isl_basic_map *bmap, int div)
3177{
3178 int i;
3179 unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
3180 isl_bool marked;
3181
3182 marked = isl_basic_map_div_is_marked_unknown(bmap, div);
3183 if (marked < 0 || marked)
3184 return isl_bool_not(marked);
3185
3186 for (i = bmap->n_div - 1; i >= 0; --i) {
3187 isl_bool known;
3188
3189 if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
3190 continue;
3191 known = isl_basic_map_div_is_known(bmap, i);
3192 if (known < 0 || !known)
3193 return known;
3194 }
3195
3196 return isl_bool_true;
3197}
3198
3199/* Remove all divs that are unknown or defined in terms of unknown divs.
3200 */
3201__isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
3202 __isl_take isl_basic_map *bmap)
3203{
3204 int i;
3205
3206 if (!bmap)
3207 return NULL;
3208
3209 for (i = bmap->n_div - 1; i >= 0; --i) {
3210 if (isl_basic_map_div_is_known(bmap, i))
3211 continue;
3212 bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
3213 if (!bmap)
3214 return NULL;
3215 i = bmap->n_div;
3216 }
3217
3218 return bmap;
3219}
3220
3221/* Remove all divs that are unknown or defined in terms of unknown divs.
3222 */
3223__isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
3224 __isl_take isl_basic_set *bset)
3225{
3226 return isl_basic_map_remove_unknown_divs(bset);
3227}
3228
3229__isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
3230{
3231 int i;
3232
3233 if (!map)
3234 return NULL;
3235 if (map->n == 0)
3236 return map;
3237
3238 map = isl_map_cow(map);
3239 if (!map)
3240 return NULL;
3241
3242 for (i = 0; i < map->n; ++i) {
3243 map->p[i] = isl_basic_map_remove_unknown_divs(map->p[i]);
3244 if (!map->p[i])
3245 goto error;
3246 }
3247 return map;
3248error:
3249 isl_map_free(map);
3250 return NULL;
3251}
3252
3253__isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
3254{
3255 return set_from_map(isl_map_remove_unknown_divs(set_to_map(set)));
3256}
3257
3258__isl_give isl_basic_set *isl_basic_set_remove_dims(
3259 __isl_take isl_basic_set *bset,
3260 enum isl_dim_type type, unsigned first, unsigned n)
3261{
3262 isl_basic_map *bmap = bset_to_bmap(bset);
3263 bmap = isl_basic_map_remove_dims(bmap, type, first, n);
3264 return bset_from_bmap(bmap);
3265}
3266
3267__isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
3268 enum isl_dim_type type, unsigned first, unsigned n)
3269{
3270 int i;
3271
3272 if (n == 0)
3273 return map;
3274
3275 map = isl_map_cow(map);
3276 if (isl_map_check_range(map, type, first, n) < 0)
3277 return isl_map_free(map);
3278
3279 for (i = 0; i < map->n; ++i) {
3280 map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
3281 isl_basic_map_offset(map->p[i], type) - 1 + first, n);
3282 if (!map->p[i])
3283 goto error;
3284 }
3285 map = isl_map_drop(map, type, first, n);
3286 return map;
3287error:
3288 isl_map_free(map);
3289 return NULL;
3290}
3291
3292__isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
3293 enum isl_dim_type type, unsigned first, unsigned n)
3294{
3295 return set_from_map(isl_map_remove_dims(set_to_map(bset),
3296 type, first, n));
3297}
3298
3299/* Project out n inputs starting at first using Fourier-Motzkin */
3300__isl_give isl_map *isl_map_remove_inputs(__isl_take isl_map *map,
3301 unsigned first, unsigned n)
3302{
3303 return isl_map_remove_dims(map, isl_dim_in, first, n);
3304}
3305
3306void isl_basic_set_print_internal(__isl_keep isl_basic_set *bset,
3307 FILE *out, int indent)
3308{
3309 isl_printer *p;
3310
3311 if (!bset) {
3312 fprintf(out, "null basic set\n");
3313 return;
3314 }
3315
3316 fprintf(out, "%*s", indent, "");
3317 fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
3318 bset->ref, bset->dim->nparam, bset->dim->n_out,
3319 bset->extra, bset->flags);
3320
3321 p = isl_printer_to_file(isl_basic_set_get_ctx(bset), out);
3322 p = isl_printer_set_dump(p, 1);
3323 p = isl_printer_set_indent(p, indent);
3324 p = isl_printer_start_line(p);
3325 p = isl_printer_print_basic_set(p, bset);
3326 p = isl_printer_end_line(p);
3327 isl_printer_free(p);
3328}
3329
3330void isl_basic_map_print_internal(__isl_keep isl_basic_map *bmap,
3331 FILE *out, int indent)
3332{
3333 isl_printer *p;
3334
3335 if (!bmap) {
3336 fprintf(out, "null basic map\n");
3337 return;
3338 }
3339
3340 fprintf(out, "%*s", indent, "");
3341 fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
3342 "flags: %x, n_name: %d\n",
3343 bmap->ref,
3344 bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
3345 bmap->extra, bmap->flags, bmap->dim->n_id);
3346
3347 p = isl_printer_to_file(isl_basic_map_get_ctx(bmap), out);
3348 p = isl_printer_set_dump(p, 1);
3349 p = isl_printer_set_indent(p, indent);
3350 p = isl_printer_start_line(p);
3351 p = isl_printer_print_basic_map(p, bmap);
3352 p = isl_printer_end_line(p);
3353 isl_printer_free(p);
3354}
3355
3356__isl_give isl_basic_map *isl_inequality_negate(__isl_take isl_basic_map *bmap,
3357 unsigned pos)
3358{
3359 isl_size total;
3360
3361 total = isl_basic_map_dim(bmap, isl_dim_all);
3362 if (total < 0)
3363 return isl_basic_map_free(bmap);
3364 if (pos >= bmap->n_ineq)
3365 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
3366 "invalid position", return isl_basic_map_free(bmap));
3367 isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
3368 isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
3369 ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
3370 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
3371 return bmap;
3372}
3373
3374__isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *space, int n,
3375 unsigned flags)
3376{
3377 if (isl_space_check_is_set(space) < 0)
3378 goto error;
3379 return isl_map_alloc_space(space, n, flags);
3380error:
3381 isl_space_free(space);
3382 return NULL;
3383}
3384
3385/* Make sure "map" has room for at least "n" more basic maps.
3386 */
3387__isl_give isl_map *isl_map_grow(__isl_take isl_map *map, int n)
3388{
3389 int i;
3390 struct isl_map *grown = NULL;
3391
3392 if (!map)
3393 return NULL;
3394 isl_assert(map->ctx, n >= 0, goto error);
3395 if (map->n + n <= map->size)
3396 return map;
3397 grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
3398 if (!grown)
3399 goto error;
3400 for (i = 0; i < map->n; ++i) {
3401 grown->p[i] = isl_basic_map_copy(map->p[i]);
3402 if (!grown->p[i])
3403 goto error;
3404 grown->n++;
3405 }
3406 isl_map_free(map);
3407 return grown;
3408error:
3409 isl_map_free(grown);
3410 isl_map_free(map);
3411 return NULL;
3412}
3413
3414/* Make sure "set" has room for at least "n" more basic sets.
3415 */
3416__isl_give isl_set *isl_set_grow(__isl_take isl_set *set, int n)
3417{
3418 return set_from_map(isl_map_grow(set_to_map(set), n));
3419}
3420
3421__isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset)
3422{
3423 return isl_map_from_basic_map(bset);
3424}
3425
3426__isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap)
3427{
3428 struct isl_map *map;
3429
3430 if (!bmap)
3431 return NULL;
3432
3433 map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
3434 return isl_map_add_basic_map(map, bmap);
3435}
3436
3437__isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
3438 __isl_take isl_basic_set *bset)
3439{
3440 return set_from_map(isl_map_add_basic_map(set_to_map(set),
3441 bset_to_bmap(bset)));
3442}
3443
3444__isl_null isl_set *isl_set_free(__isl_take isl_set *set)
3445{
3446 return isl_map_free(set);
3447}
3448
3449void isl_set_print_internal(__isl_keep isl_set *set, FILE *out, int indent)
3450{
3451 int i;
3452
3453 if (!set) {
3454 fprintf(out, "null set\n");
3455 return;
3456 }
3457
3458 fprintf(out, "%*s", indent, "");
3459 fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
3460 set->ref, set->n, set->dim->nparam, set->dim->n_out,
3461 set->flags);
3462 for (i = 0; i < set->n; ++i) {
3463 fprintf(out, "%*s", indent, "");
3464 fprintf(out, "basic set %d:\n", i);
3465 isl_basic_set_print_internal(set->p[i], out, indent+4);
3466 }
3467}
3468
3469void isl_map_print_internal(__isl_keep isl_map *map, FILE *out, int indent)
3470{
3471 int i;
3472
3473 if (!map) {
3474 fprintf(out, "null map\n");
3475 return;
3476 }
3477
3478 fprintf(out, "%*s", indent, "");
3479 fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
3480 "flags: %x, n_name: %d\n",
3481 map->ref, map->n, map->dim->nparam, map->dim->n_in,
3482 map->dim->n_out, map->flags, map->dim->n_id);
3483 for (i = 0; i < map->n; ++i) {
3484 fprintf(out, "%*s", indent, "");
3485 fprintf(out, "basic map %d:\n", i);
3486 isl_basic_map_print_internal(map->p[i], out, indent+4);
3487 }
3488}
3489
3490/* Check that the space of "bset" is the same as that of the domain of "bmap".
3491 */
3492static isl_stat isl_basic_map_check_compatible_domain(
3493 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3494{
3495 isl_bool ok;
3496
3497 ok = isl_basic_map_compatible_domain(bmap, bset);
3498 if (ok < 0)
3499 return isl_stat_error;
3500 if (!ok)
3501 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3502 "incompatible spaces", return isl_stat_error);
3503
3504 return isl_stat_ok;
3505}
3506
3507__isl_give isl_basic_map *isl_basic_map_intersect_domain(
3508 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3509{
3510 struct isl_basic_map *bmap_domain;
3511 isl_size dim;
3512
3513 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3514 goto error;
3515
3516 dim = isl_basic_set_dim(bset, isl_dim_set);
3517 if (dim < 0)
3518 goto error;
3519 if (dim != 0 &&
3520 isl_basic_map_check_compatible_domain(bmap, bset) < 0)
3521 goto error;
3522
3523 bmap = isl_basic_map_cow(bmap);
3524 if (!bmap)
3525 goto error;
3526 bmap = isl_basic_map_extend(bmap,
3527 bset->n_div, bset->n_eq, bset->n_ineq);
3528 bmap_domain = isl_basic_map_from_domain(bset);
3529 bmap = add_constraints(bmap, bmap_domain, 0, 0);
3530
3531 bmap = isl_basic_map_simplify(bmap);
3532 return isl_basic_map_finalize(bmap);
3533error:
3534 isl_basic_map_free(bmap);
3535 isl_basic_set_free(bset);
3536 return NULL;
3537}
3538
3539/* Check that the space of "bset" is the same as that of the range of "bmap".
3540 */
3541static isl_stat isl_basic_map_check_compatible_range(
3542 __isl_keep isl_basic_map *bmap, __isl_keep isl_basic_set *bset)
3543{
3544 isl_bool ok;
3545
3546 ok = isl_basic_map_compatible_range(bmap, bset);
3547 if (ok < 0)
3548 return isl_stat_error;
3549 if (!ok)
3550 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
3551 "incompatible spaces", return isl_stat_error);
3552
3553 return isl_stat_ok;
3554}
3555
3556__isl_give isl_basic_map *isl_basic_map_intersect_range(
3557 __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *bset)
3558{
3559 struct isl_basic_map *bmap_range;
3560 isl_size dim;
3561
3562 if (isl_basic_map_check_equal_params(bmap, bset_to_bmap(bset)) < 0)
3563 goto error;
3564
3565 dim = isl_basic_set_dim(bset, isl_dim_set);
3566 if (dim < 0)
3567 goto error;
3568 if (dim != 0 && isl_basic_map_check_compatible_range(bmap, bset) < 0)
3569 goto error;
3570
3571 if (isl_basic_set_plain_is_universe(bset)) {
3572 isl_basic_set_free(bset);
3573 return bmap;
3574 }
3575
3576 bmap = isl_basic_map_cow(bmap);
3577 if (!bmap)
3578 goto error;
3579 bmap = isl_basic_map_extend(bmap,
3580 bset->n_div, bset->n_eq, bset->n_ineq);
3581 bmap_range = bset_to_bmap(bset);
3582 bmap = add_constraints(bmap, bmap_range, 0, 0);
3583
3584 bmap = isl_basic_map_simplify(bmap);
3585 return isl_basic_map_finalize(bmap);
3586error:
3587 isl_basic_map_free(bmap);
3588 isl_basic_set_free(bset);
3589 return NULL;
3590}
3591
3592isl_bool isl_basic_map_contains(__isl_keep isl_basic_map *bmap,
3593 __isl_keep isl_vec *vec)
3594{
3595 int i;
3596 isl_size total;
3597 isl_int s;
3598
3599 total = isl_basic_map_dim(bmap, isl_dim_all);
3600 if (total < 0 || !vec)
3601 return isl_bool_error;
3602
3603 if (1 + total != vec->size)
3604 return isl_bool_false;
3605
3606 isl_int_init(s);
3607
3608 for (i = 0; i < bmap->n_eq; ++i) {
3609 isl_seq_inner_product(vec->el, bmap->eq[i], 1 + total, &s);
3610 if (!isl_int_is_zero(s)) {
3611 isl_int_clear(s);
3612 return isl_bool_false;
3613 }
3614 }
3615
3616 for (i = 0; i < bmap->n_ineq; ++i) {
3617 isl_seq_inner_product(vec->el, bmap->ineq[i], 1 + total, &s);
3618 if (isl_int_is_neg(s)) {
3619 isl_int_clear(s);
3620 return isl_bool_false;
3621 }
3622 }
3623
3624 isl_int_clear(s);
3625
3626 return isl_bool_true;
3627}
3628
3629isl_bool isl_basic_set_contains(__isl_keep isl_basic_set *bset,
3630 __isl_keep isl_vec *vec)
3631{
3632 return isl_basic_map_contains(bset_to_bmap(bset), vec);
3633}
3634
3635__isl_give isl_basic_map *isl_basic_map_intersect(
3636 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
3637{
3638 struct isl_vec *sample = NULL;
3639 isl_space *space1, *space2;
3640 isl_size dim1, dim2, nparam1, nparam2;
3641
3642 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
3643 goto error;
3644 space1 = isl_basic_map_peek_space(bmap1);
3645 space2 = isl_basic_map_peek_space(bmap2);
3646 dim1 = isl_space_dim(space1, isl_dim_all);
3647 dim2 = isl_space_dim(space2, isl_dim_all);
3648 nparam1 = isl_space_dim(space1, isl_dim_param);
3649 nparam2 = isl_space_dim(space2, isl_dim_param);
3650 if (dim1 < 0 || dim2 < 0 || nparam1 < 0 || nparam2 < 0)
3651 goto error;
3652 if (dim1 == nparam1 && dim2 != nparam2)
3653 return isl_basic_map_intersect(bmap2, bmap1);
3654
3655 if (dim2 != nparam2 &&
3656 isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
3657 goto error;
3658
3659 if (isl_basic_map_plain_is_empty(bmap1)) {
3660 isl_basic_map_free(bmap2);
3661 return bmap1;
3662 }
3663 if (isl_basic_map_plain_is_empty(bmap2)) {
3664 isl_basic_map_free(bmap1);
3665 return bmap2;
3666 }
3667
3668 if (bmap1->sample &&
3669 isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
3670 isl_basic_map_contains(bmap2, bmap1->sample) > 0)
3671 sample = isl_vec_copy(bmap1->sample);
3672 else if (bmap2->sample &&
3673 isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
3674 isl_basic_map_contains(bmap2, bmap2->sample) > 0)
3675 sample = isl_vec_copy(bmap2->sample);
3676
3677 bmap1 = isl_basic_map_cow(bmap1);
3678 if (!bmap1)
3679 goto error;
3680 bmap1 = isl_basic_map_extend(bmap1,
3681 bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
3682 bmap1 = add_constraints(bmap1, bmap2, 0, 0);
3683
3684 if (!bmap1)
3685 isl_vec_free(sample);
3686 else if (sample) {
3687 isl_vec_free(bmap1->sample);
3688 bmap1->sample = sample;
3689 }
3690
3691 bmap1 = isl_basic_map_simplify(bmap1);
3692 return isl_basic_map_finalize(bmap1);
3693error:
3694 if (sample)
3695 isl_vec_free(sample);
3696 isl_basic_map_free(bmap1);
3697 isl_basic_map_free(bmap2);
3698 return NULL;
3699}
3700
3701__isl_give isl_basic_set *isl_basic_set_intersect(
3702 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3703{
3704 return bset_from_bmap(isl_basic_map_intersect(bset_to_bmap(bset1),
3705 bset_to_bmap(bset2)));
3706}
3707
3708__isl_give isl_basic_set *isl_basic_set_intersect_params(
3709 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
3710{
3711 return isl_basic_set_intersect(bset1, bset2);
3712}
3713
3714/* Special case of isl_map_intersect, where both map1 and map2
3715 * are convex, without any divs and such that either map1 or map2
3716 * contains a single constraint. This constraint is then simply
3717 * added to the other map.
3718 */
3719static __isl_give isl_map *map_intersect_add_constraint(
3720 __isl_take isl_map *map1, __isl_take isl_map *map2)
3721{
3722 isl_assert(map1->ctx, map1->n == 1, goto error);
3723 isl_assert(map2->ctx, map1->n == 1, goto error);
3724 isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
3725 isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
3726
3727 if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
3728 return isl_map_intersect(map2, map1);
3729
3730 map1 = isl_map_cow(map1);
3731 if (!map1)
3732 goto error;
3733 if (isl_map_plain_is_empty(map1)) {
3734 isl_map_free(map2);
3735 return map1;
3736 }
3737 if (map2->p[0]->n_eq == 1)
3738 map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
3739 else
3740 map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
3741 map2->p[0]->ineq[0]);
3742
3743 map1->p[0] = isl_basic_map_simplify(map1->p[0]);
3744 map1->p[0] = isl_basic_map_finalize(map1->p[0]);
3745 if (!map1->p[0])
3746 goto error;
3747
3748 if (isl_basic_map_plain_is_empty(map1->p[0])) {
3749 isl_basic_map_free(map1->p[0]);
3750 map1->n = 0;
3751 }
3752
3753 isl_map_free(map2);
3754
3755 map1 = isl_map_unmark_normalized(map1);
3756 return map1;
3757error:
3758 isl_map_free(map1);
3759 isl_map_free(map2);
3760 return NULL;
3761}
3762
3763/* map2 may be either a parameter domain or a map living in the same
3764 * space as map1.
3765 */
3766static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
3767 __isl_take isl_map *map2)
3768{
3769 unsigned flags = 0;
3770 isl_bool equal;
3771 isl_map *result;
3772 int i, j;
3773 isl_size dim2, nparam2;
3774
3775 if (!map1 || !map2)
3776 goto error;
3777
3778 if ((isl_map_plain_is_empty(map1) ||
3779 isl_map_plain_is_universe(map2)) &&
3780 isl_space_is_equal(map1->dim, map2->dim)) {
3781 isl_map_free(map2);
3782 return map1;
3783 }
3784 if ((isl_map_plain_is_empty(map2) ||
3785 isl_map_plain_is_universe(map1)) &&
3786 isl_space_is_equal(map1->dim, map2->dim)) {
3787 isl_map_free(map1);
3788 return map2;
3789 }
3790
3791 if (map1->n == 1 && map2->n == 1 &&
3792 map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
3793 isl_space_is_equal(map1->dim, map2->dim) &&
3794 (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
3795 map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
3796 return map_intersect_add_constraint(map1, map2);
3797
3798 equal = isl_map_plain_is_equal(map1, map2);
3799 if (equal < 0)
3800 goto error;
3801 if (equal) {
3802 isl_map_free(map2);
3803 return map1;
3804 }
3805
3806 dim2 = isl_map_dim(map2, isl_dim_all);
3807 nparam2 = isl_map_dim(map2, isl_dim_param);
3808 if (dim2 < 0 || nparam2 < 0)
3809 goto error;
3810 if (dim2 != nparam2)
3811 isl_assert(map1->ctx,
3812 isl_space_is_equal(map1->dim, map2->dim), goto error);
3813
3814 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
3815 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
3816 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
3817
3818 result = isl_map_alloc_space(isl_space_copy(map1->dim),
3819 map1->n * map2->n, flags);
3820 if (!result)
3821 goto error;
3822 for (i = 0; i < map1->n; ++i)
3823 for (j = 0; j < map2->n; ++j) {
3824 struct isl_basic_map *part;
3825 part = isl_basic_map_intersect(
3826 isl_basic_map_copy(map1->p[i]),
3827 isl_basic_map_copy(map2->p[j]));
3828 if (isl_basic_map_is_empty(part) < 0)
3829 part = isl_basic_map_free(part);
3830 result = isl_map_add_basic_map(result, part);
3831 if (!result)
3832 goto error;
3833 }
3834 isl_map_free(map1);
3835 isl_map_free(map2);
3836 return result;
3837error:
3838 isl_map_free(map1);
3839 isl_map_free(map2);
3840 return NULL;
3841}
3842
3843static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
3844 __isl_take isl_map *map2)
3845{
3846 if (isl_map_check_equal_space(map1, map2) < 0)
3847 goto error;
3848 return map_intersect_internal(map1, map2);
3849error:
3850 isl_map_free(map1);
3851 isl_map_free(map2);
3852 return NULL;
3853}
3854
3855__isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
3856 __isl_take isl_map *map2)
3857{
3858 isl_map_align_params_bin(&map1, &map2);
3859 return map_intersect(map1, map2);
3860}
3861
3862__isl_give isl_set *isl_set_intersect(__isl_take isl_set *set1,
3863 __isl_take isl_set *set2)
3864{
3865 return set_from_map(isl_map_intersect(set_to_map(set1),
3866 set_to_map(set2)));
3867}
3868
3869/* map_intersect_internal accepts intersections
3870 * with parameter domains, so we can just call that function.
3871 */
3872__isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map,
3873 __isl_take isl_set *params)
3874{
3875 isl_map_align_params_set(&map, &params);
3876 return map_intersect_internal(map, params);
3877}
3878
3879__isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
3880 __isl_take isl_set *params)
3881{
3882 return isl_map_intersect_params(set, params);
3883}
3884
3885__isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap)
3886{
3887 isl_space *space;
3888 unsigned pos;
3889 isl_size n1, n2;
3890
3891 if (!bmap)
3892 return NULL;
3893 bmap = isl_basic_map_cow(bmap);
3894 if (!bmap)
3895 return NULL;
3896 space = isl_space_reverse(isl_space_copy(bmap->dim));
3897 pos = isl_basic_map_offset(bmap, isl_dim_in);
3898 n1 = isl_basic_map_dim(bmap, isl_dim_in);
3899 n2 = isl_basic_map_dim(bmap, isl_dim_out);
3900 if (n1 < 0 || n2 < 0)
3901 bmap = isl_basic_map_free(bmap);
3902 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
3903 return isl_basic_map_reset_space(bmap, space);
3904}
3905
3906/* Given a basic map A -> (B -> C), return the corresponding basic map
3907 * A -> (C -> B).
3908 */
3909static __isl_give isl_basic_map *isl_basic_map_range_reverse(
3910 __isl_take isl_basic_map *bmap)
3911{
3912 isl_space *space;
3913 isl_size offset, n1, n2;
3914
3915 space = isl_basic_map_peek_space(bmap);
3916 if (isl_space_check_range_is_wrapping(space) < 0)
3917 return isl_basic_map_free(bmap);
3918 offset = isl_basic_map_var_offset(bmap, isl_dim_out);
3919 n1 = isl_space_wrapped_dim(space, isl_dim_out, isl_dim_in);
3920 n2 = isl_space_wrapped_dim(space, isl_dim_out, isl_dim_out);
3921 if (offset < 0 || n1 < 0 || n2 < 0)
3922 return isl_basic_map_free(bmap);
3923
3924 bmap = isl_basic_map_swap_vars(bmap, 1 + offset, n1, n2);
3925
3926 space = isl_basic_map_take_space(bmap);
3927 space = isl_space_range_reverse(space);
3928 bmap = isl_basic_map_restore_space(bmap, space);
3929
3930 return bmap;
3931}
3932
3933static __isl_give isl_basic_map *basic_map_space_reset(
3934 __isl_take isl_basic_map *bmap, enum isl_dim_type type)
3935{
3936 isl_space *space;
3937
3938 if (!bmap)
3939 return NULL;
3940 if (!isl_space_is_named_or_nested(bmap->dim, type))
3941 return bmap;
3942
3943 space = isl_basic_map_get_space(bmap);
3944 space = isl_space_reset(space, type);
3945 bmap = isl_basic_map_reset_space(bmap, space);
3946 return bmap;
3947}
3948
3949__isl_give isl_basic_map *isl_basic_map_insert_dims(
3950 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
3951 unsigned pos, unsigned n)
3952{
3953 isl_bool rational, is_empty;
3954 isl_space *res_space;
3955 struct isl_basic_map *res;
3956 struct isl_dim_map *dim_map;
3957 isl_size total;
3958 unsigned off;
3959 enum isl_dim_type t;
3960
3961 if (n == 0)
3962 return basic_map_space_reset(bmap, type);
3963
3964 is_empty = isl_basic_map_plain_is_empty(bmap);
3965 total = isl_basic_map_dim(bmap, isl_dim_all);
3966 if (is_empty < 0 || total < 0)
3967 return isl_basic_map_free(bmap);
3968 res_space = isl_space_insert_dims(isl_basic_map_get_space(bmap),
3969 type, pos, n);
3970 if (!res_space)
3971 return isl_basic_map_free(bmap);
3972 if (is_empty) {
3973 isl_basic_map_free(bmap);
3974 return isl_basic_map_empty(res_space);
3975 }
3976
3977 dim_map = isl_dim_map_alloc(bmap->ctx, total + n);
3978 off = 0;
3979 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
3980 isl_size dim;
3981
3982 if (t != type) {
3983 isl_dim_map_dim(dim_map, bmap->dim, t, off);
3984 } else {
3985 isl_size size = isl_basic_map_dim(bmap, t);
3986 if (size < 0)
3987 dim_map = isl_dim_map_free(dim_map);
3988 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3989 0, pos, off);
3990 isl_dim_map_dim_range(dim_map, bmap->dim, t,
3991 pos, size - pos, off + pos + n);
3992 }
3993 dim = isl_space_dim(res_space, t);
3994 if (dim < 0)
3995 dim_map = isl_dim_map_free(dim_map);
3996 off += dim;
3997 }
3998 isl_dim_map_div(dim_map, bmap, off);
3999
4000 res = isl_basic_map_alloc_space(res_space,
4001 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4002 rational = isl_basic_map_is_rational(bmap);
4003 if (rational < 0)
4004 res = isl_basic_map_free(res);
4005 if (rational)
4006 res = isl_basic_map_set_rational(res);
4007 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4008 return isl_basic_map_finalize(res);
4009}
4010
4011__isl_give isl_basic_set *isl_basic_set_insert_dims(
4012 __isl_take isl_basic_set *bset,
4013 enum isl_dim_type type, unsigned pos, unsigned n)
4014{
4015 return isl_basic_map_insert_dims(bset, type, pos, n);
4016}
4017
4018__isl_give isl_basic_map *isl_basic_map_add_dims(__isl_take isl_basic_map *bmap,
4019 enum isl_dim_type type, unsigned n)
4020{
4021 isl_size dim;
4022
4023 dim = isl_basic_map_dim(bmap, type);
4024 if (dim < 0)
4025 return isl_basic_map_free(bmap);
4026 return isl_basic_map_insert_dims(bmap, type, dim, n);
4027}
4028
4029__isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
4030 enum isl_dim_type type, unsigned n)
4031{
4032 if (!bset)
4033 return NULL;
4034 isl_assert(bset->ctx, type != isl_dim_in, goto error);
4035 return isl_basic_map_add_dims(bset, type, n);
4036error:
4037 isl_basic_set_free(bset);
4038 return NULL;
4039}
4040
4041static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
4042 enum isl_dim_type type)
4043{
4044 isl_space *space;
4045
4046 if (!map || !isl_space_is_named_or_nested(map->dim, type))
4047 return map;
4048
4049 space = isl_map_get_space(map);
4050 space = isl_space_reset(space, type);
4051 map = isl_map_reset_space(map, space);
4052 return map;
4053}
4054
4055__isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
4056 enum isl_dim_type type, unsigned pos, unsigned n)
4057{
4058 int i;
4059 isl_space *space;
4060
4061 if (n == 0)
4062 return map_space_reset(map, type);
4063
4064 map = isl_map_cow(map);
4065 if (!map)
4066 return NULL;
4067
4068 for (i = 0; i < map->n; ++i) {
4069 map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
4070 if (!map->p[i])
4071 goto error;
4072 }
4073
4074 space = isl_map_take_space(map);
4075 space = isl_space_insert_dims(space, type, pos, n);
4076 map = isl_map_restore_space(map, space);
4077
4078 return map;
4079error:
4080 isl_map_free(map);
4081 return NULL;
4082}
4083
4084__isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
4085 enum isl_dim_type type, unsigned pos, unsigned n)
4086{
4087 return isl_map_insert_dims(set, type, pos, n);
4088}
4089
4090__isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
4091 enum isl_dim_type type, unsigned n)
4092{
4093 isl_size dim;
4094
4095 dim = isl_map_dim(map, type);
4096 if (dim < 0)
4097 return isl_map_free(map);
4098 return isl_map_insert_dims(map, type, dim, n);
4099}
4100
4101__isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
4102 enum isl_dim_type type, unsigned n)
4103{
4104 if (!set)
4105 return NULL;
4106 isl_assert(set->ctx, type != isl_dim_in, goto error);
4107 return set_from_map(isl_map_add_dims(set_to_map(set), type, n));
4108error:
4109 isl_set_free(set);
4110 return NULL;
4111}
4112
4113__isl_give isl_basic_map *isl_basic_map_move_dims(
4114 __isl_take isl_basic_map *bmap,
4115 enum isl_dim_type dst_type, unsigned dst_pos,
4116 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4117{
4118 isl_space *space;
4119 struct isl_dim_map *dim_map;
4120 struct isl_basic_map *res;
4121 enum isl_dim_type t;
4122 isl_size total;
4123 unsigned off;
4124
4125 if (!bmap)
4126 return NULL;
4127 if (n == 0) {
4128 bmap = isl_basic_map_reset(bmap, src_type);
4129 bmap = isl_basic_map_reset(bmap, dst_type);
4130 return bmap;
4131 }
4132
4133 if (isl_basic_map_check_range(bmap, src_type, src_pos, n) < 0)
4134 return isl_basic_map_free(bmap);
4135
4136 if (dst_type == src_type && dst_pos == src_pos)
4137 return bmap;
4138
4139 isl_assert(bmap->ctx, dst_type != src_type, goto error);
4140
4141 if (pos(bmap->dim, dst_type) + dst_pos ==
4142 pos(bmap->dim, src_type) + src_pos +
4143 ((src_type < dst_type) ? n : 0)) {
4144 space = isl_basic_map_take_space(bmap);
4145 space = isl_space_move_dims(space, dst_type, dst_pos,
4146 src_type, src_pos, n);
4147 bmap = isl_basic_map_restore_space(bmap, space);
4148 bmap = isl_basic_map_finalize(bmap);
4149
4150 return bmap;
4151 }
4152
4153 total = isl_basic_map_dim(bmap, isl_dim_all);
4154 if (total < 0)
4155 return isl_basic_map_free(bmap);
4156 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4157
4158 off = 0;
4159 space = isl_basic_map_peek_space(bmap);
4160 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4161 isl_size size = isl_space_dim(space, t);
4162 if (size < 0)
4163 dim_map = isl_dim_map_free(dim_map);
4164 if (t == dst_type) {
4165 isl_dim_map_dim_range(dim_map, space, t,
4166 0, dst_pos, off);
4167 off += dst_pos;
4168 isl_dim_map_dim_range(dim_map, space, src_type,
4169 src_pos, n, off);
4170 off += n;
4171 isl_dim_map_dim_range(dim_map, space, t,
4172 dst_pos, size - dst_pos, off);
4173 off += size - dst_pos;
4174 } else if (t == src_type) {
4175 isl_dim_map_dim_range(dim_map, space, t,
4176 0, src_pos, off);
4177 off += src_pos;
4178 isl_dim_map_dim_range(dim_map, space, t,
4179 src_pos + n, size - src_pos - n, off);
4180 off += size - src_pos - n;
4181 } else {
4182 isl_dim_map_dim(dim_map, space, t, off);
4183 off += size;
4184 }
4185 }
4186 isl_dim_map_div(dim_map, bmap, off);
4187
4188 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4189 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4190 bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4191 space = isl_basic_map_take_space(bmap);
4192 space = isl_space_move_dims(space, dst_type, dst_pos,
4193 src_type, src_pos, n);
4194 bmap = isl_basic_map_restore_space(bmap, space);
4195 if (!bmap)
4196 goto error;
4197
4198 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
4199 bmap = isl_basic_map_gauss(bmap, NULL);
4200 bmap = isl_basic_map_finalize(bmap);
4201
4202 return bmap;
4203error:
4204 isl_basic_map_free(bmap);
4205 return NULL;
4206}
4207
4208__isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
4209 enum isl_dim_type dst_type, unsigned dst_pos,
4210 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4211{
4212 isl_basic_map *bmap = bset_to_bmap(bset);
4213 bmap = isl_basic_map_move_dims(bmap, dst_type, dst_pos,
4214 src_type, src_pos, n);
4215 return bset_from_bmap(bmap);
4216}
4217
4218__isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
4219 enum isl_dim_type dst_type, unsigned dst_pos,
4220 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4221{
4222 if (!set)
4223 return NULL;
4224 isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
4225 return set_from_map(isl_map_move_dims(set_to_map(set),
4226 dst_type, dst_pos, src_type, src_pos, n));
4227error:
4228 isl_set_free(set);
4229 return NULL;
4230}
4231
4232__isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
4233 enum isl_dim_type dst_type, unsigned dst_pos,
4234 enum isl_dim_type src_type, unsigned src_pos, unsigned n)
4235{
4236 int i;
4237 isl_space *space;
4238
4239 if (n == 0) {
4240 map = isl_map_reset(map, src_type);
4241 map = isl_map_reset(map, dst_type);
4242 return map;
4243 }
4244
4245 if (isl_map_check_range(map, src_type, src_pos, n))
4246 return isl_map_free(map);
4247
4248 if (dst_type == src_type && dst_pos == src_pos)
4249 return map;
4250
4251 isl_assert(map->ctx, dst_type != src_type, goto error);
4252
4253 map = isl_map_cow(map);
4254 if (!map)
4255 return NULL;
4256
4257 for (i = 0; i < map->n; ++i) {
4258 map->p[i] = isl_basic_map_move_dims(map->p[i],
4259 dst_type, dst_pos,
4260 src_type, src_pos, n);
4261 if (!map->p[i])
4262 goto error;
4263 }
4264
4265 space = isl_map_take_space(map);
4266 space = isl_space_move_dims(space, dst_type, dst_pos,
4267 src_type, src_pos, n);
4268 map = isl_map_restore_space(map, space);
4269
4270 return map;
4271error:
4272 isl_map_free(map);
4273 return NULL;
4274}
4275
4276/* Move the specified dimensions to the last columns right before
4277 * the divs. Don't change the dimension specification of bmap.
4278 * That's the responsibility of the caller.
4279 */
4280static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
4281 enum isl_dim_type type, unsigned first, unsigned n)
4282{
4283 isl_space *space;
4284 struct isl_dim_map *dim_map;
4285 struct isl_basic_map *res;
4286 enum isl_dim_type t;
4287 isl_size total;
4288 unsigned off;
4289
4290 if (!bmap)
4291 return NULL;
4292 if (isl_basic_map_offset(bmap, type) + first + n ==
4293 isl_basic_map_offset(bmap, isl_dim_div))
4294 return bmap;
4295
4296 total = isl_basic_map_dim(bmap, isl_dim_all);
4297 if (total < 0)
4298 return isl_basic_map_free(bmap);
4299 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4300
4301 off = 0;
4302 space = isl_basic_map_peek_space(bmap);
4303 for (t = isl_dim_param; t <= isl_dim_out; ++t) {
4304 isl_size size = isl_space_dim(space, t);
4305 if (size < 0)
4306 dim_map = isl_dim_map_free(dim_map);
4307 if (t == type) {
4308 isl_dim_map_dim_range(dim_map, space, t,
4309 0, first, off);
4310 off += first;
4311 isl_dim_map_dim_range(dim_map, space, t,
4312 first, n, total - bmap->n_div - n);
4313 isl_dim_map_dim_range(dim_map, space, t,
4314 first + n, size - (first + n), off);
4315 off += size - (first + n);
4316 } else {
4317 isl_dim_map_dim(dim_map, space, t, off);
4318 off += size;
4319 }
4320 }
4321 isl_dim_map_div(dim_map, bmap, off + n);
4322
4323 res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
4324 bmap->n_div, bmap->n_eq, bmap->n_ineq);
4325 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
4326 return res;
4327}
4328
4329/* Insert "n" rows in the divs of "bmap".
4330 *
4331 * The number of columns is not changed, which means that the last
4332 * dimensions of "bmap" are being reintepreted as the new divs.
4333 * The space of "bmap" is not adjusted, however, which means
4334 * that "bmap" is left in an inconsistent state. Removing "n" dimensions
4335 * from the space of "bmap" is the responsibility of the caller.
4336 */
4337static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
4338 int n)
4339{
4340 int i;
4341 size_t row_size;
4342 isl_int **new_div;
4343 isl_int *old;
4344
4345 bmap = isl_basic_map_cow(bmap);
4346 if (!bmap)
4347 return NULL;
4348
4349 row_size = isl_basic_map_offset(bmap, isl_dim_div) + bmap->extra;
4350 old = bmap->block2.data;
4351 bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
4352 (bmap->extra + n) * (1 + row_size));
4353 if (!bmap->block2.data)
4354 return isl_basic_map_free(bmap);
4355 new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
4356 if (!new_div)
4357 return isl_basic_map_free(bmap);
4358 for (i = 0; i < n; ++i) {
4359 new_div[i] = bmap->block2.data +
4360 (bmap->extra + i) * (1 + row_size);
4361 isl_seq_clr(new_div[i], 1 + row_size);
4362 }
4363 for (i = 0; i < bmap->extra; ++i)
4364 new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
4365 free(bmap->div);
4366 bmap->div = new_div;
4367 bmap->n_div += n;
4368 bmap->extra += n;
4369
4370 return bmap;
4371}
4372
4373/* Drop constraints from "bmap" that only involve the variables
4374 * of "type" in the range [first, first + n] that are not related
4375 * to any of the variables outside that interval.
4376 * These constraints cannot influence the values for the variables
4377 * outside the interval, except in case they cause "bmap" to be empty.
4378 * Only drop the constraints if "bmap" is known to be non-empty.
4379 */
4380static __isl_give isl_basic_map *drop_irrelevant_constraints(
4381 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
4382 unsigned first, unsigned n)
4383{
4384 int i;
4385 int *groups;
4386 isl_size dim, n_div;
4387 isl_bool non_empty;
4388
4389 non_empty = isl_basic_map_plain_is_non_empty(bmap);
4390 if (non_empty < 0)
4391 return isl_basic_map_free(bmap);
4392 if (!non_empty)
4393 return bmap;
4394
4395 dim = isl_basic_map_dim(bmap, isl_dim_all);
4396 n_div = isl_basic_map_dim(bmap, isl_dim_div);
4397 if (dim < 0 || n_div < 0)
4398 return isl_basic_map_free(bmap);
4399 groups = isl_calloc_array(isl_basic_map_get_ctx(bmap), int, dim);
4400 if (!groups)
4401 return isl_basic_map_free(bmap);
4402 first += isl_basic_map_offset(bmap, type) - 1;
4403 for (i = 0; i < first; ++i)
4404 groups[i] = -1;
4405 for (i = first + n; i < dim - n_div; ++i)
4406 groups[i] = -1;
4407
4408 bmap = isl_basic_map_drop_unrelated_constraints(bmap, groups);
4409
4410 return bmap;
4411}
4412
4413/* Turn the n dimensions of type type, starting at first
4414 * into existentially quantified variables.
4415 *
4416 * If a subset of the projected out variables are unrelated
4417 * to any of the variables that remain, then the constraints
4418 * involving this subset are simply dropped first.
4419 */
4420__isl_give isl_basic_map *isl_basic_map_project_out(
4421 __isl_take isl_basic_map *bmap,
4422 enum isl_dim_type type, unsigned first, unsigned n)
4423{
4424 isl_bool empty;
4425 isl_space *space;
4426
4427 if (n == 0)
4428 return basic_map_space_reset(bmap, type);
4429 if (type == isl_dim_div)
4430 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
4431 "cannot project out existentially quantified variables",
4432 return isl_basic_map_free(bmap));
4433
4434 empty = isl_basic_map_plain_is_empty(bmap);
4435 if (empty < 0)
4436 return isl_basic_map_free(bmap);
4437 if (empty)
4438 bmap = isl_basic_map_set_to_empty(bmap);
4439
4440 bmap = drop_irrelevant_constraints(bmap, type, first, n);
4441 if (!bmap)
4442 return NULL;
4443
4444 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
4445 return isl_basic_map_remove_dims(bmap, type, first, n);
4446
4447 if (isl_basic_map_check_range(bmap, type, first, n) < 0)
4448 return isl_basic_map_free(bmap);
4449
4450 bmap = move_last(bmap, type, first, n);
4451 bmap = isl_basic_map_cow(bmap);
4452 bmap = insert_div_rows(bmap, n);
4453
4454 space = isl_basic_map_take_space(bmap);
4455 space = isl_space_drop_dims(space, type, first, n);
4456 bmap = isl_basic_map_restore_space(bmap, space);
4457 bmap = isl_basic_map_simplify(bmap);
4458 bmap = isl_basic_map_drop_redundant_divs(bmap);
4459 return isl_basic_map_finalize(bmap);
4460}
4461
4462/* Turn the n dimensions of type type, starting at first
4463 * into existentially quantified variables.
4464 */
4465__isl_give isl_basic_set *isl_basic_set_project_out(
4466 __isl_take isl_basic_set *bset, enum isl_dim_type type,
4467 unsigned first, unsigned n)
4468{
4469 return bset_from_bmap(isl_basic_map_project_out(bset_to_bmap(bset),
4470 type, first, n));
4471}
4472
4473/* Turn the n dimensions of type type, starting at first
4474 * into existentially quantified variables.
4475 */
4476__isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
4477 enum isl_dim_type type, unsigned first, unsigned n)
4478{
4479 int i;
4480 isl_space *space;
4481
4482 if (n == 0)
4483 return map_space_reset(map, type);
4484
4485 if (isl_map_check_range(map, type, first, n) < 0)
4486 return isl_map_free(map);
4487
4488 map = isl_map_cow(map);
4489 if (!map)
4490 return NULL;
4491
4492 for (i = 0; i < map->n; ++i) {
4493 map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
4494 if (!map->p[i])
4495 goto error;
4496 }
4497
4498 if (map->n > 1)
4499 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4500 map = isl_map_unmark_normalized(map);
4501
4502 space = isl_map_take_space(map);
4503 space = isl_space_drop_dims(space, type, first, n);
4504 map = isl_map_restore_space(map, space);
4505
4506 return map;
4507error:
4508 isl_map_free(map);
4509 return NULL;
4510}
4511
4512#undef TYPE
4513#define TYPE isl_map
4514#include "isl_project_out_all_params_templ.c"
4515
4516/* Turn all the dimensions of type "type", except the "n" starting at "first"
4517 * into existentially quantified variables.
4518 */
4519__isl_give isl_map *isl_map_project_onto(__isl_take isl_map *map,
4520 enum isl_dim_type type, unsigned first, unsigned n)
4521{
4522 isl_size dim;
4523
4524 dim = isl_map_dim(map, type);
4525 if (isl_map_check_range(map, type, first, n) < 0 || dim < 0)
4526 return isl_map_free(map);
4527 map = isl_map_project_out(map, type, first + n, dim - (first + n));
4528 map = isl_map_project_out(map, type, 0, first);
4529 return map;
4530}
4531
4532/* Turn the n dimensions of type type, starting at first
4533 * into existentially quantified variables.
4534 */
4535__isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
4536 enum isl_dim_type type, unsigned first, unsigned n)
4537{
4538 return set_from_map(isl_map_project_out(set_to_map(set),
4539 type, first, n));
4540}
4541
4542/* If "set" involves a parameter with identifier "id",
4543 * then turn it into an existentially quantified variable.
4544 */
4545__isl_give isl_set *isl_set_project_out_param_id(__isl_take isl_set *set,
4546 __isl_take isl_id *id)
4547{
4548 int pos;
4549
4550 if (!set || !id)
4551 goto error;
4552 pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
4553 isl_id_free(id);
4554 if (pos < 0)
4555 return set;
4556 return isl_set_project_out(set, isl_dim_param, pos, 1);
4557error:
4558 isl_set_free(set);
4559 isl_id_free(id);
4560 return NULL;
4561}
4562
4563/* If "set" involves any of the parameters with identifiers in "list",
4564 * then turn them into existentially quantified variables.
4565 */
4566__isl_give isl_set *isl_set_project_out_param_id_list(__isl_take isl_set *set,
4567 __isl_take isl_id_list *list)
4568{
4569 int i;
4570 isl_size n;
4571
4572 n = isl_id_list_size(list);
4573 if (n < 0)
4574 goto error;
4575 for (i = 0; i < n; ++i) {
4576 isl_id *id;
4577
4578 id = isl_id_list_get_at(list, i);
4579 set = isl_set_project_out_param_id(set, id);
4580 }
4581
4582 isl_id_list_free(list);
4583 return set;
4584error:
4585 isl_id_list_free(list);
4586 isl_set_free(set);
4587 return NULL;
4588}
4589
4590/* Project out all parameters from "set" by existentially quantifying
4591 * over them.
4592 */
4593__isl_give isl_set *isl_set_project_out_all_params(__isl_take isl_set *set)
4594{
4595 return set_from_map(isl_map_project_out_all_params(set_to_map(set)));
4596}
4597
4598/* Return a map that projects the elements in "set" onto their
4599 * "n" set dimensions starting at "first".
4600 * "type" should be equal to isl_dim_set.
4601 */
4602__isl_give isl_map *isl_set_project_onto_map(__isl_take isl_set *set,
4603 enum isl_dim_type type, unsigned first, unsigned n)
4604{
4605 int i;
4606 isl_map *map;
4607
4608 if (type != isl_dim_set)
4609 isl_die(isl_set_get_ctx(set), isl_error_invalid,
4610 "only set dimensions can be projected out", goto error);
4611 if (isl_set_check_range(set, type, first, n) < 0)
4612 return isl_set_free(set);
4613
4614 map = isl_map_from_domain(set);
4615 map = isl_map_add_dims(map, isl_dim_out, n);
4616 for (i = 0; i < n; ++i)
4617 map = isl_map_equate(map, isl_dim_in, first + i,
4618 isl_dim_out, i);
4619 return map;
4620error:
4621 isl_set_free(set);
4622 return NULL;
4623}
4624
4625static __isl_give isl_basic_map *add_divs(__isl_take isl_basic_map *bmap,
4626 unsigned n)
4627{
4628 int i, j;
4629 isl_size total;
4630
4631 total = isl_basic_map_dim(bmap, isl_dim_all);
4632 if (total < 0)
4633 return isl_basic_map_free(bmap);
4634 for (i = 0; i < n; ++i) {
4635 j = isl_basic_map_alloc_div(bmap);
4636 if (j < 0)
4637 goto error;
4638 isl_seq_clr(bmap->div[j], 1 + 1 + total);
4639 }
4640 return bmap;
4641error:
4642 isl_basic_map_free(bmap);
4643 return NULL;
4644}
4645
4646/* Does "bmap2" apply to the range of "bmap1" (ignoring parameters)?
4647 */
4648isl_bool isl_basic_map_applies_range(__isl_keep isl_basic_map *bmap1,
4649 __isl_keep isl_basic_map *bmap2)
4650{
4651 isl_space *space1, *space2;
4652
4653 space1 = isl_basic_map_peek_space(bmap1);
4654 space2 = isl_basic_map_peek_space(bmap2);
4655 return isl_space_tuple_is_equal(space1, isl_dim_out,
4656 space2, isl_dim_in);
4657}
4658
4659/* Check that "bmap2" applies to the range of "bmap1" (ignoring parameters).
4660 */
4661static isl_stat isl_basic_map_check_applies_range(
4662 __isl_keep isl_basic_map *bmap1, __isl_keep isl_basic_map *bmap2)
4663{
4664 isl_bool equal;
4665
4666 equal = isl_basic_map_applies_range(bmap1, bmap2);
4667 if (equal < 0)
4668 return isl_stat_error;
4669 if (!equal)
4670 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4671 "spaces don't match", return isl_stat_error);
4672 return isl_stat_ok;
4673}
4674
4675__isl_give isl_basic_map *isl_basic_map_apply_range(
4676 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
4677{
4678 isl_space *space_result = NULL;
4679 struct isl_basic_map *bmap;
4680 isl_size n_in, n_out, n, nparam;
4681 unsigned total, pos;
4682 struct isl_dim_map *dim_map1, *dim_map2;
4683
4684 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4685 goto error;
4686 if (isl_basic_map_check_applies_range(bmap1, bmap2) < 0)
4687 goto error;
4688
4689 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4690 n_out = isl_basic_map_dim(bmap2, isl_dim_out);
4691 n = isl_basic_map_dim(bmap1, isl_dim_out);
4692 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4693 if (n_in < 0 || n_out < 0 || n < 0 || nparam < 0)
4694 goto error;
4695
4696 space_result = isl_space_join(isl_basic_map_get_space(bmap1),
4697 isl_basic_map_get_space(bmap2));
4698
4699 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
4700 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4701 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
4702 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4703 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
4704 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4705 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
4706 isl_dim_map_div(dim_map1, bmap1, pos += n_out);
4707 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4708 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4709 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4710
4711 bmap = isl_basic_map_alloc_space(space_result,
4712 bmap1->n_div + bmap2->n_div + n,
4713 bmap1->n_eq + bmap2->n_eq,
4714 bmap1->n_ineq + bmap2->n_ineq);
4715 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4716 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4717 bmap = add_divs(bmap, n);
4718 bmap = isl_basic_map_simplify(bmap);
4719 bmap = isl_basic_map_drop_redundant_divs(bmap);
4720 return isl_basic_map_finalize(bmap);
4721error:
4722 isl_basic_map_free(bmap1);
4723 isl_basic_map_free(bmap2);
4724 return NULL;
4725}
4726
4727__isl_give isl_basic_set *isl_basic_set_apply(__isl_take isl_basic_set *bset,
4728 __isl_take isl_basic_map *bmap)
4729{
4730 if (isl_basic_map_check_compatible_domain(bmap, bset) < 0)
4731 goto error;
4732
4733 return bset_from_bmap(isl_basic_map_apply_range(bset_to_bmap(bset),
4734 bmap));
4735error:
4736 isl_basic_set_free(bset);
4737 isl_basic_map_free(bmap);
4738 return NULL;
4739}
4740
4741__isl_give isl_basic_map *isl_basic_map_apply_domain(
4742 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
4743{
4744 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
4745 goto error;
4746 if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_in,
4747 bmap2->dim, isl_dim_in))
4748 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
4749 "spaces don't match", goto error);
4750
4751 bmap1 = isl_basic_map_reverse(bmap1);
4752 bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
4753 return isl_basic_map_reverse(bmap1);
4754error:
4755 isl_basic_map_free(bmap1);
4756 isl_basic_map_free(bmap2);
4757 return NULL;
4758}
4759
4760/* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
4761 * A \cap B -> f(A) + f(B)
4762 */
4763__isl_give isl_basic_map *isl_basic_map_sum(__isl_take isl_basic_map *bmap1,
4764 __isl_take isl_basic_map *bmap2)
4765{
4766 isl_size n_in, n_out, nparam;
4767 unsigned total, pos;
4768 struct isl_basic_map *bmap = NULL;
4769 struct isl_dim_map *dim_map1, *dim_map2;
4770 int i;
4771
4772 if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
4773 goto error;
4774
4775 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
4776 n_in = isl_basic_map_dim(bmap1, isl_dim_in);
4777 n_out = isl_basic_map_dim(bmap1, isl_dim_out);
4778 if (nparam < 0 || n_in < 0 || n_out < 0)
4779 goto error;
4780
4781 total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
4782 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
4783 dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
4784 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
4785 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
4786 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
4787 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
4788 isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
4789 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
4790 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
4791 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
4792
4793 bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
4794 bmap1->n_div + bmap2->n_div + 2 * n_out,
4795 bmap1->n_eq + bmap2->n_eq + n_out,
4796 bmap1->n_ineq + bmap2->n_ineq);
4797 for (i = 0; i < n_out; ++i) {
4798 int j = isl_basic_map_alloc_equality(bmap);
4799 if (j < 0)
4800 goto error;
4801 isl_seq_clr(bmap->eq[j], 1+total);
4802 isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
4803 isl_int_set_si(bmap->eq[j][1+pos+i], 1);
4804 isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
4805 }
4806 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
4807 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
4808 bmap = add_divs(bmap, 2 * n_out);
4809
4810 bmap = isl_basic_map_simplify(bmap);
4811 return isl_basic_map_finalize(bmap);
4812error:
4813 isl_basic_map_free(bmap);
4814 isl_basic_map_free(bmap1);
4815 isl_basic_map_free(bmap2);
4816 return NULL;
4817}
4818
4819/* Given two maps A -> f(A) and B -> g(B), construct a map
4820 * A \cap B -> f(A) + f(B)
4821 */
4822__isl_give isl_map *isl_map_sum(__isl_take isl_map *map1,
4823 __isl_take isl_map *map2)
4824{
4825 struct isl_map *result;
4826 int i, j;
4827
4828 if (isl_map_check_equal_space(map1, map2) < 0)
4829 goto error;
4830
4831 result = isl_map_alloc_space(isl_space_copy(map1->dim),
4832 map1->n * map2->n, 0);
4833 if (!result)
4834 goto error;
4835 for (i = 0; i < map1->n; ++i)
4836 for (j = 0; j < map2->n; ++j) {
4837 struct isl_basic_map *part;
4838 part = isl_basic_map_sum(
4839 isl_basic_map_copy(map1->p[i]),
4840 isl_basic_map_copy(map2->p[j]));
4841 if (isl_basic_map_is_empty(part))
4842 isl_basic_map_free(part);
4843 else
4844 result = isl_map_add_basic_map(result, part);
4845 if (!result)
4846 goto error;
4847 }
4848 isl_map_free(map1);
4849 isl_map_free(map2);
4850 return result;
4851error:
4852 isl_map_free(map1);
4853 isl_map_free(map2);
4854 return NULL;
4855}
4856
4857__isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
4858 __isl_take isl_set *set2)
4859{
4860 return set_from_map(isl_map_sum(set_to_map(set1), set_to_map(set2)));
4861}
4862
4863/* Given a basic map A -> f(A), construct A -> -f(A).
4864 */
4865__isl_give isl_basic_map *isl_basic_map_neg(__isl_take isl_basic_map *bmap)
4866{
4867 int i, j;
4868 unsigned off;
4869 isl_size n;
4870
4871 bmap = isl_basic_map_cow(bmap);
4872 n = isl_basic_map_dim(bmap, isl_dim_out);
4873 if (n < 0)
4874 return isl_basic_map_free(bmap);
4875
4876 off = isl_basic_map_offset(bmap, isl_dim_out);
4877 for (i = 0; i < bmap->n_eq; ++i)
4878 for (j = 0; j < n; ++j)
4879 isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
4880 for (i = 0; i < bmap->n_ineq; ++i)
4881 for (j = 0; j < n; ++j)
4882 isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
4883 for (i = 0; i < bmap->n_div; ++i)
4884 for (j = 0; j < n; ++j)
4885 isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
4886 bmap = isl_basic_map_gauss(bmap, NULL);
4887 return isl_basic_map_finalize(bmap);
4888}
4889
4890__isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
4891{
4892 return isl_basic_map_neg(bset);
4893}
4894
4895/* Given a map A -> f(A), construct A -> -f(A).
4896 */
4897__isl_give isl_map *isl_map_neg(__isl_take isl_map *map)
4898{
4899 int i;
4900
4901 map = isl_map_cow(map);
4902 if (!map)
4903 return NULL;
4904
4905 for (i = 0; i < map->n; ++i) {
4906 map->p[i] = isl_basic_map_neg(map->p[i]);
4907 if (!map->p[i])
4908 goto error;
4909 }
4910
4911 return map;
4912error:
4913 isl_map_free(map);
4914 return NULL;
4915}
4916
4917__isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
4918{
4919 return set_from_map(isl_map_neg(set_to_map(set)));
4920}
4921
4922/* Given a basic map A -> f(A) and an integer d, construct a basic map
4923 * A -> floor(f(A)/d).
4924 */
4925__isl_give isl_basic_map *isl_basic_map_floordiv(__isl_take isl_basic_map *bmap,
4926 isl_int d)
4927{
4928 isl_size n_in, n_out, nparam;
4929 unsigned total, pos;
4930 struct isl_basic_map *result = NULL;
4931 struct isl_dim_map *dim_map;
4932 int i;
4933
4934 nparam = isl_basic_map_dim(bmap, isl_dim_param);
4935 n_in = isl_basic_map_dim(bmap, isl_dim_in);
4936 n_out = isl_basic_map_dim(bmap, isl_dim_out);
4937 if (nparam < 0 || n_in < 0 || n_out < 0)
4938 return isl_basic_map_free(bmap);
4939
4940 total = nparam + n_in + n_out + bmap->n_div + n_out;
4941 dim_map = isl_dim_map_alloc(bmap->ctx, total);
4942 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
4943 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
4944 isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
4945 isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
4946
4947 result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
4948 bmap->n_div + n_out,
4949 bmap->n_eq, bmap->n_ineq + 2 * n_out);
4950 result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
4951 result = add_divs(result, n_out);
4952 for (i = 0; i < n_out; ++i) {
4953 int j;
4954 j = isl_basic_map_alloc_inequality(result);
4955 if (j < 0)
4956 goto error;
4957 isl_seq_clr(result->ineq[j], 1+total);
4958 isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
4959 isl_int_set_si(result->ineq[j][1+pos+i], 1);
4960 j = isl_basic_map_alloc_inequality(result);
4961 if (j < 0)
4962 goto error;
4963 isl_seq_clr(result->ineq[j], 1+total);
4964 isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
4965 isl_int_set_si(result->ineq[j][1+pos+i], -1);
4966 isl_int_sub_ui(result->ineq[j][0], d, 1);
4967 }
4968
4969 result = isl_basic_map_simplify(result);
4970 return isl_basic_map_finalize(result);
4971error:
4972 isl_basic_map_free(result);
4973 return NULL;
4974}
4975
4976/* Given a map A -> f(A) and an integer d, construct a map
4977 * A -> floor(f(A)/d).
4978 */
4979__isl_give isl_map *isl_map_floordiv(__isl_take isl_map *map, isl_int d)
4980{
4981 int i;
4982
4983 map = isl_map_cow(map);
4984 if (!map)
4985 return NULL;
4986
4987 ISL_F_CLR(map, ISL_MAP_DISJOINT);
4988 for (i = 0; i < map->n; ++i) {
4989 map->p[i] = isl_basic_map_floordiv(map->p[i], d);
4990 if (!map->p[i])
4991 goto error;
4992 }
4993 map = isl_map_unmark_normalized(map);
4994
4995 return map;
4996error:
4997 isl_map_free(map);
4998 return NULL;
4999}
5000
5001/* Given a map A -> f(A) and an integer d, construct a map
5002 * A -> floor(f(A)/d).
5003 */
5004__isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
5005 __isl_take isl_val *d)
5006{
5007 if (!map || !d)
5008 goto error;
5009 if (!isl_val_is_int(d))
5010 isl_die(isl_val_get_ctx(d), isl_error_invalid,
5011 "expecting integer denominator", goto error);
5012 map = isl_map_floordiv(map, d->n);
5013 isl_val_free(d);
5014 return map;
5015error:
5016 isl_map_free(map);
5017 isl_val_free(d);
5018 return NULL;
5019}
5020
5021static __isl_give isl_basic_map *var_equal(__isl_take isl_basic_map *bmap,
5022 unsigned pos)
5023{
5024 int i;
5025 isl_size nparam;
5026 isl_size n_in;
5027 isl_size total;
5028
5029 total = isl_basic_map_dim(bmap, isl_dim_all);
5030 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5031 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5032 if (total < 0 || nparam < 0 || n_in < 0)
5033 return isl_basic_map_free(bmap);
5034 i = isl_basic_map_alloc_equality(bmap);
5035 if (i < 0)
5036 goto error;
5037 isl_seq_clr(bmap->eq[i], 1 + total);
5038 isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
5039 isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
5040 return isl_basic_map_finalize(bmap);
5041error:
5042 isl_basic_map_free(bmap);
5043 return NULL;
5044}
5045
5046/* Add a constraint to "bmap" expressing i_pos < o_pos
5047 */
5048static __isl_give isl_basic_map *var_less(__isl_take isl_basic_map *bmap,
5049 unsigned pos)
5050{
5051 int i;
5052 isl_size nparam;
5053 isl_size n_in;
5054 isl_size total;
5055
5056 total = isl_basic_map_dim(bmap, isl_dim_all);
5057 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5058 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5059 if (total < 0 || nparam < 0 || n_in < 0)
5060 return isl_basic_map_free(bmap);
5061 i = isl_basic_map_alloc_inequality(bmap);
5062 if (i < 0)
5063 goto error;
5064 isl_seq_clr(bmap->ineq[i], 1 + total);
5065 isl_int_set_si(bmap->ineq[i][0], -1);
5066 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
5067 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
5068 return isl_basic_map_finalize(bmap);
5069error:
5070 isl_basic_map_free(bmap);
5071 return NULL;
5072}
5073
5074/* Add a constraint to "bmap" expressing i_pos <= o_pos
5075 */
5076static __isl_give isl_basic_map *var_less_or_equal(
5077 __isl_take isl_basic_map *bmap, unsigned pos)
5078{
5079 int i;
5080 isl_size nparam;
5081 isl_size n_in;
5082 isl_size total;
5083
5084 total = isl_basic_map_dim(bmap, isl_dim_all);
5085 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5086 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5087 if (total < 0 || nparam < 0 || n_in < 0)
5088 return isl_basic_map_free(bmap);
5089 i = isl_basic_map_alloc_inequality(bmap);
5090 if (i < 0)
5091 goto error;
5092 isl_seq_clr(bmap->ineq[i], 1 + total);
5093 isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
5094 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
5095 return isl_basic_map_finalize(bmap);
5096error:
5097 isl_basic_map_free(bmap);
5098 return NULL;
5099}
5100
5101/* Add a constraint to "bmap" expressing i_pos > o_pos
5102 */
5103static __isl_give isl_basic_map *var_more(__isl_take isl_basic_map *bmap,
5104 unsigned pos)
5105{
5106 int i;
5107 isl_size nparam;
5108 isl_size n_in;
5109 isl_size total;
5110
5111 total = isl_basic_map_dim(bmap, isl_dim_all);
5112 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5113 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5114 if (total < 0 || nparam < 0 || n_in < 0)
5115 return isl_basic_map_free(bmap);
5116 i = isl_basic_map_alloc_inequality(bmap);
5117 if (i < 0)
5118 goto error;
5119 isl_seq_clr(bmap->ineq[i], 1 + total);
5120 isl_int_set_si(bmap->ineq[i][0], -1);
5121 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
5122 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
5123 return isl_basic_map_finalize(bmap);
5124error:
5125 isl_basic_map_free(bmap);
5126 return NULL;
5127}
5128
5129/* Add a constraint to "bmap" expressing i_pos >= o_pos
5130 */
5131static __isl_give isl_basic_map *var_more_or_equal(
5132 __isl_take isl_basic_map *bmap, unsigned pos)
5133{
5134 int i;
5135 isl_size nparam;
5136 isl_size n_in;
5137 isl_size total;
5138
5139 total = isl_basic_map_dim(bmap, isl_dim_all);
5140 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5141 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5142 if (total < 0 || nparam < 0 || n_in < 0)
5143 return isl_basic_map_free(bmap);
5144 i = isl_basic_map_alloc_inequality(bmap);
5145 if (i < 0)
5146 goto error;
5147 isl_seq_clr(bmap->ineq[i], 1 + total);
5148 isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
5149 isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
5150 return isl_basic_map_finalize(bmap);
5151error:
5152 isl_basic_map_free(bmap);
5153 return NULL;
5154}
5155
5156__isl_give isl_basic_map *isl_basic_map_equal(
5157 __isl_take isl_space *space, unsigned n_equal)
5158{
5159 int i;
5160 struct isl_basic_map *bmap;
5161 bmap = isl_basic_map_alloc_space(space, 0, n_equal, 0);
5162 if (!bmap)
5163 return NULL;
5164 for (i = 0; i < n_equal && bmap; ++i)
5165 bmap = var_equal(bmap, i);
5166 return isl_basic_map_finalize(bmap);
5167}
5168
5169/* Return a relation on of dimension "space" expressing i_[0..pos] << o_[0..pos]
5170 */
5171__isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *space,
5172 unsigned pos)
5173{
5174 int i;
5175 struct isl_basic_map *bmap;
5176 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5177 if (!bmap)
5178 return NULL;
5179 for (i = 0; i < pos && bmap; ++i)
5180 bmap = var_equal(bmap, i);
5181 if (bmap)
5182 bmap = var_less(bmap, pos);
5183 return isl_basic_map_finalize(bmap);
5184}
5185
5186/* Return a relation on "space" expressing i_[0..pos] <<= o_[0..pos]
5187 */
5188__isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
5189 __isl_take isl_space *space, unsigned pos)
5190{
5191 int i;
5192 isl_basic_map *bmap;
5193
5194 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5195 for (i = 0; i < pos; ++i)
5196 bmap = var_equal(bmap, i);
5197 bmap = var_less_or_equal(bmap, pos);
5198 return isl_basic_map_finalize(bmap);
5199}
5200
5201/* Return a relation on "space" expressing i_pos > o_pos
5202 */
5203__isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *space,
5204 unsigned pos)
5205{
5206 int i;
5207 struct isl_basic_map *bmap;
5208 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5209 if (!bmap)
5210 return NULL;
5211 for (i = 0; i < pos && bmap; ++i)
5212 bmap = var_equal(bmap, i);
5213 if (bmap)
5214 bmap = var_more(bmap, pos);
5215 return isl_basic_map_finalize(bmap);
5216}
5217
5218/* Return a relation on "space" expressing i_[0..pos] >>= o_[0..pos]
5219 */
5220__isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
5221 __isl_take isl_space *space, unsigned pos)
5222{
5223 int i;
5224 isl_basic_map *bmap;
5225
5226 bmap = isl_basic_map_alloc_space(space, 0, pos, 1);
5227 for (i = 0; i < pos; ++i)
5228 bmap = var_equal(bmap, i);
5229 bmap = var_more_or_equal(bmap, pos);
5230 return isl_basic_map_finalize(bmap);
5231}
5232
5233static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *space,
5234 unsigned n, int equal)
5235{
5236 struct isl_map *map;
5237 int i;
5238
5239 if (n == 0 && equal)
5240 return isl_map_universe(space);
5241
5242 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5243
5244 for (i = 0; i + 1 < n; ++i)
5245 map = isl_map_add_basic_map(map,
5246 isl_basic_map_less_at(isl_space_copy(space), i));
5247 if (n > 0) {
5248 if (equal)
5249 map = isl_map_add_basic_map(map,
5250 isl_basic_map_less_or_equal_at(space, n - 1));
5251 else
5252 map = isl_map_add_basic_map(map,
5253 isl_basic_map_less_at(space, n - 1));
5254 } else
5255 isl_space_free(space);
5256
5257 return map;
5258}
5259
5260static __isl_give isl_map *map_lex_lte(__isl_take isl_space *space, int equal)
5261{
5262 if (!space)
5263 return NULL;
5264 return map_lex_lte_first(space, space->n_out, equal);
5265}
5266
5267__isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *space,
5268 unsigned n)
5269{
5270 return map_lex_lte_first(space, n, 0);
5271}
5272
5273__isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *space,
5274 unsigned n)
5275{
5276 return map_lex_lte_first(space, n, 1);
5277}
5278
5279__isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_space)
5280{
5281 return map_lex_lte(isl_space_map_from_set(set_space), 0);
5282}
5283
5284__isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_space)
5285{
5286 return map_lex_lte(isl_space_map_from_set(set_space), 1);
5287}
5288
5289static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *space,
5290 unsigned n, int equal)
5291{
5292 struct isl_map *map;
5293 int i;
5294
5295 if (n == 0 && equal)
5296 return isl_map_universe(space);
5297
5298 map = isl_map_alloc_space(isl_space_copy(space), n, ISL_MAP_DISJOINT);
5299
5300 for (i = 0; i + 1 < n; ++i)
5301 map = isl_map_add_basic_map(map,
5302 isl_basic_map_more_at(isl_space_copy(space), i));
5303 if (n > 0) {
5304 if (equal)
5305 map = isl_map_add_basic_map(map,
5306 isl_basic_map_more_or_equal_at(space, n - 1));
5307 else
5308 map = isl_map_add_basic_map(map,
5309 isl_basic_map_more_at(space, n - 1));
5310 } else
5311 isl_space_free(space);
5312
5313 return map;
5314}
5315
5316static __isl_give isl_map *map_lex_gte(__isl_take isl_space *space, int equal)
5317{
5318 if (!space)
5319 return NULL;
5320 return map_lex_gte_first(space, space->n_out, equal);
5321}
5322
5323__isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *space,
5324 unsigned n)
5325{
5326 return map_lex_gte_first(space, n, 0);
5327}
5328
5329__isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *space,
5330 unsigned n)
5331{
5332 return map_lex_gte_first(space, n, 1);
5333}
5334
5335__isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_space)
5336{
5337 return map_lex_gte(isl_space_map_from_set(set_space), 0);
5338}
5339
5340__isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_space)
5341{
5342 return map_lex_gte(isl_space_map_from_set(set_space), 1);
5343}
5344
5345__isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
5346 __isl_take isl_set *set2)
5347{
5348 isl_map *map;
5349 map = isl_map_lex_le(isl_set_get_space(set1));
5350 map = isl_map_intersect_domain(map, set1);
5351 map = isl_map_intersect_range(map, set2);
5352 return map;
5353}
5354
5355__isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
5356 __isl_take isl_set *set2)
5357{
5358 isl_map *map;
5359 map = isl_map_lex_lt(isl_set_get_space(set1));
5360 map = isl_map_intersect_domain(map, set1);
5361 map = isl_map_intersect_range(map, set2);
5362 return map;
5363}
5364
5365__isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
5366 __isl_take isl_set *set2)
5367{
5368 isl_map *map;
5369 map = isl_map_lex_ge(isl_set_get_space(set1));
5370 map = isl_map_intersect_domain(map, set1);
5371 map = isl_map_intersect_range(map, set2);
5372 return map;
5373}
5374
5375__isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
5376 __isl_take isl_set *set2)
5377{
5378 isl_map *map;
5379 map = isl_map_lex_gt(isl_set_get_space(set1));
5380 map = isl_map_intersect_domain(map, set1);
5381 map = isl_map_intersect_range(map, set2);
5382 return map;
5383}
5384
5385__isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
5386 __isl_take isl_map *map2)
5387{
5388 isl_map *map;
5389 map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
5390 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5391 map = isl_map_apply_range(map, isl_map_reverse(map2));
5392 return map;
5393}
5394
5395__isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
5396 __isl_take isl_map *map2)
5397{
5398 isl_map *map;
5399 map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
5400 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5401 map = isl_map_apply_range(map, isl_map_reverse(map2));
5402 return map;
5403}
5404
5405__isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
5406 __isl_take isl_map *map2)
5407{
5408 isl_map *map;
5409 map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
5410 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5411 map = isl_map_apply_range(map, isl_map_reverse(map2));
5412 return map;
5413}
5414
5415__isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
5416 __isl_take isl_map *map2)
5417{
5418 isl_map *map;
5419 map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
5420 map = isl_map_apply_domain(map, isl_map_reverse(map1));
5421 map = isl_map_apply_range(map, isl_map_reverse(map2));
5422 return map;
5423}
5424
5425/* For the div d = floor(f/m) at position "div", add the constraint
5426 *
5427 * f - m d >= 0
5428 */
5429static __isl_give isl_basic_map *add_upper_div_constraint(
5430 __isl_take isl_basic_map *bmap, unsigned div)
5431{
5432 int i;
5433 isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5434 isl_size n_div;
5435 unsigned pos;
5436
5437 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5438 if (v_div < 0 || n_div < 0)
5439 return isl_basic_map_free(bmap);
5440 pos = v_div + div;
5441 i = isl_basic_map_alloc_inequality(bmap);
5442 if (i < 0)
5443 return isl_basic_map_free(bmap);
5444 isl_seq_cpy(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5445 isl_int_neg(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5446
5447 return bmap;
5448}
5449
5450/* For the div d = floor(f/m) at position "div", add the constraint
5451 *
5452 * -(f-(m-1)) + m d >= 0
5453 */
5454static __isl_give isl_basic_map *add_lower_div_constraint(
5455 __isl_take isl_basic_map *bmap, unsigned div)
5456{
5457 int i;
5458 isl_size v_div = isl_basic_map_var_offset(bmap, isl_dim_div);
5459 isl_size n_div;
5460 unsigned pos;
5461
5462 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5463 if (v_div < 0 || n_div < 0)
5464 return isl_basic_map_free(bmap);
5465 pos = v_div + div;
5466 i = isl_basic_map_alloc_inequality(bmap);
5467 if (i < 0)
5468 return isl_basic_map_free(bmap);
5469 isl_seq_neg(bmap->ineq[i], bmap->div[div] + 1, 1 + v_div + n_div);
5470 isl_int_set(bmap->ineq[i][1 + pos], bmap->div[div][0]);
5471 isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
5472 isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
5473
5474 return bmap;
5475}
5476
5477/* For the div d = floor(f/m) at position "pos", add the constraints
5478 *
5479 * f - m d >= 0
5480 * -(f-(m-1)) + m d >= 0
5481 *
5482 * Note that the second constraint is the negation of
5483 *
5484 * f - m d >= m
5485 */
5486__isl_give isl_basic_map *isl_basic_map_add_div_constraints(
5487 __isl_take isl_basic_map *bmap, unsigned pos)
5488{
5489 bmap = add_upper_div_constraint(bmap, pos);
5490 bmap = add_lower_div_constraint(bmap, pos);
5491 return bmap;
5492}
5493
5494/* For each known div d = floor(f/m), add the constraints
5495 *
5496 * f - m d >= 0
5497 * -(f-(m-1)) + m d >= 0
5498 *
5499 * Remove duplicate constraints in case of some these div constraints
5500 * already appear in "bmap".
5501 */
5502__isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
5503 __isl_take isl_basic_map *bmap)
5504{
5505 isl_size n_div;
5506
5507 n_div = isl_basic_map_dim(bmap, isl_dim_div);
5508 if (n_div < 0)
5509 return isl_basic_map_free(bmap);
5510 if (n_div == 0)
5511 return bmap;
5512
5513 bmap = add_known_div_constraints(bmap);
5514 bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
5515 bmap = isl_basic_map_finalize(bmap);
5516 return bmap;
5517}
5518
5519/* Add the div constraint of sign "sign" for div "div" of "bmap".
5520 *
5521 * In particular, if this div is of the form d = floor(f/m),
5522 * then add the constraint
5523 *
5524 * f - m d >= 0
5525 *
5526 * if sign < 0 or the constraint
5527 *
5528 * -(f-(m-1)) + m d >= 0
5529 *
5530 * if sign > 0.
5531 */
5532__isl_give isl_basic_map *isl_basic_map_add_div_constraint(
5533 __isl_take isl_basic_map *bmap, unsigned div, int sign)
5534{
5535 if (sign < 0)
5536 return add_upper_div_constraint(bmap, div);
5537 else
5538 return add_lower_div_constraint(bmap, div);
5539}
5540
5541__isl_give isl_basic_set *isl_basic_map_underlying_set(
5542 __isl_take isl_basic_map *bmap)
5543{
5544 isl_space *space;
5545
5546 if (!bmap)
5547 goto error;
5548 if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
5549 bmap->n_div == 0 &&
5550 !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
5551 !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
5552 return bset_from_bmap(bmap);
5553 bmap = isl_basic_map_cow(bmap);
5554 if (!bmap)
5555 return NULL;
5556 space = isl_basic_map_take_space(bmap);
5557 space = isl_space_underlying(space, bmap->n_div);
5558 bmap = isl_basic_map_restore_space(bmap, space);
5559 if (!bmap)
5560 return NULL;
5561 bmap->extra -= bmap->n_div;
5562 bmap->n_div = 0;
5563 bmap = isl_basic_map_finalize(bmap);
5564 return bset_from_bmap(bmap);
5565error:
5566 isl_basic_map_free(bmap);
5567 return NULL;
5568}
5569
5570__isl_give isl_basic_set *isl_basic_set_underlying_set(
5571 __isl_take isl_basic_set *bset)
5572{
5573 return isl_basic_map_underlying_set(bset_to_bmap(bset));
5574}
5575
5576/* Replace each element in "list" by the result of applying
5577 * isl_basic_map_underlying_set to the element.
5578 */
5579__isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
5580 __isl_take isl_basic_map_list *list)
5581{
5582 int i;
5583 isl_size n;
5584
5585 n = isl_basic_map_list_n_basic_map(list);
5586 if (n < 0)
5587 goto error;
5588
5589 for (i = 0; i < n; ++i) {
5590 isl_basic_map *bmap;
5591 isl_basic_set *bset;
5592
5593 bmap = isl_basic_map_list_get_basic_map(list, i);
5594 bset = isl_basic_set_underlying_set(bmap);
5595 list = isl_basic_set_list_set_basic_set(list, i, bset);
5596 }
5597
5598 return list;
5599error:
5600 isl_basic_map_list_free(list);
5601 return NULL;
5602}
5603
5604__isl_give isl_basic_map *isl_basic_map_overlying_set(
5605 __isl_take isl_basic_set *bset, __isl_take isl_basic_map *like)
5606{
5607 struct isl_basic_map *bmap;
5608 struct isl_ctx *ctx;
5609 isl_size dim, bmap_total;
5610 unsigned total;
5611 int i;
5612
5613 if (!bset || !like)
5614 goto error;
5615 ctx = bset->ctx;
5616 if (isl_basic_set_check_no_params(bset) < 0 ||
5617 isl_basic_set_check_no_locals(bset) < 0)
5618 goto error;
5619 dim = isl_basic_set_dim(bset, isl_dim_set);
5620 bmap_total = isl_basic_map_dim(like, isl_dim_all);
5621 if (dim < 0 || bmap_total < 0)
5622 goto error;
5623 isl_assert(ctx, dim == bmap_total, goto error);
5624 if (like->n_div == 0) {
5625 isl_space *space = isl_basic_map_get_space(like);
5626 isl_basic_map_free(like);
5627 return isl_basic_map_reset_space(bset, space);
5628 }
5629 bset = isl_basic_set_cow(bset);
5630 if (!bset)
5631 goto error;
5632 total = dim + bset->extra;
5633 bmap = bset_to_bmap(bset);
5634 isl_space_free(isl_basic_map_take_space(bmap));
5635 bmap = isl_basic_map_restore_space(bmap, isl_basic_map_get_space(like));
5636 if (!bmap)
5637 goto error;
5638 bmap->n_div = like->n_div;
5639 bmap->extra += like->n_div;
5640 if (bmap->extra) {
5641 unsigned ltotal;
5642 isl_int **div;
5643 ltotal = total - bmap->extra + like->extra;
5644 if (ltotal > total)
5645 ltotal = total;
5646 bmap->block2 = isl_blk_extend(ctx, bmap->block2,
5647 bmap->extra * (1 + 1 + total));
5648 if (isl_blk_is_error(bmap->block2))
5649 goto error;
5650 div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
5651 if (!div)
5652 goto error;
5653 bmap->div = div;
5654 for (i = 0; i < bmap->extra; ++i)
5655 bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
5656 for (i = 0; i < like->n_div; ++i) {
5657 isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
5658 isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
5659 }
5660 bmap = isl_basic_map_add_known_div_constraints(bmap);
5661 }
5662 isl_basic_map_free(like);
5663 bmap = isl_basic_map_simplify(bmap);
5664 bmap = isl_basic_map_finalize(bmap);
5665 return bmap;
5666error:
5667 isl_basic_map_free(like);
5668 isl_basic_set_free(bset);
5669 return NULL;
5670}
5671
5672__isl_give isl_basic_set *isl_basic_set_from_underlying_set(
5673 __isl_take isl_basic_set *bset, __isl_take isl_basic_set *like)
5674{
5675 return bset_from_bmap(isl_basic_map_overlying_set(bset,
5676 bset_to_bmap(like)));
5677}
5678
5679__isl_give isl_set *isl_map_underlying_set(__isl_take isl_map *map)
5680{
5681 int i;
5682
5683 map = isl_map_cow(map);
5684 if (!map)
5685 return NULL;
5686 map->dim = isl_space_cow(map->dim);
5687 if (!map->dim)
5688 goto error;
5689
5690 for (i = 1; i < map->n; ++i)
5691 isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
5692 goto error);
5693 for (i = 0; i < map->n; ++i) {
5694 map->p[i] = bset_to_bmap(
5695 isl_basic_map_underlying_set(map->p[i]));
5696 if (!map->p[i])
5697 goto error;
5698 }
5699 if (map->n == 0)
5700 map->dim = isl_space_underlying(map->dim, 0);
5701 else {
5702 isl_space_free(map->dim);
5703 map->dim = isl_space_copy(map->p[0]->dim);
5704 }
5705 if (!map->dim)
5706 goto error;
5707 return set_from_map(map);
5708error:
5709 isl_map_free(map);
5710 return NULL;
5711}
5712
5713/* Replace the space of "bmap" by "space".
5714 *
5715 * If the space of "bmap" is identical to "space" (including the identifiers
5716 * of the input and output dimensions), then simply return the original input.
5717 */
5718__isl_give isl_basic_map *isl_basic_map_reset_space(
5719 __isl_take isl_basic_map *bmap, __isl_take isl_space *space)
5720{
5721 isl_bool equal;
5722 isl_space *bmap_space;
5723
5724 bmap_space = isl_basic_map_peek_space(bmap);
5725 equal = isl_space_is_equal(bmap_space, space);
5726 if (equal >= 0 && equal)
5727 equal = isl_space_has_equal_ids(bmap_space, space);
5728 if (equal < 0)
5729 goto error;
5730 if (equal) {
5731 isl_space_free(space);
5732 return bmap;
5733 }
5734 isl_space_free(isl_basic_map_take_space(bmap));
5735 bmap = isl_basic_map_restore_space(bmap, space);
5736
5737 bmap = isl_basic_map_finalize(bmap);
5738
5739 return bmap;
5740error:
5741 isl_basic_map_free(bmap);
5742 isl_space_free(space);
5743 return NULL;
5744}
5745
5746__isl_give isl_basic_set *isl_basic_set_reset_space(
5747 __isl_take isl_basic_set *bset, __isl_take isl_space *space)
5748{
5749 return bset_from_bmap(isl_basic_map_reset_space(bset_to_bmap(bset),
5750 space));
5751}
5752
5753/* Check that the total dimensions of "map" and "space" are the same.
5754 */
5755static isl_stat check_map_space_equal_total_dim(__isl_keep isl_map *map,
5756 __isl_keep isl_space *space)
5757{
5758 isl_size dim1, dim2;
5759
5760 dim1 = isl_map_dim(map, isl_dim_all);
5761 dim2 = isl_space_dim(space, isl_dim_all);
5762 if (dim1 < 0 || dim2 < 0)
5763 return isl_stat_error;
5764 if (dim1 == dim2)
5765 return isl_stat_ok;
5766 isl_die(isl_map_get_ctx(map), isl_error_invalid,
5767 "total dimensions do not match", return isl_stat_error);
5768}
5769
5770__isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
5771 __isl_take isl_space *space)
5772{
5773 int i;
5774
5775 map = isl_map_cow(map);
5776 if (!map || !space)
5777 goto error;
5778
5779 for (i = 0; i < map->n; ++i) {
5780 map->p[i] = isl_basic_map_reset_space(map->p[i],
5781 isl_space_copy(space));
5782 if (!map->p[i])
5783 goto error;
5784 }
5785 isl_space_free(isl_map_take_space(map));
5786 map = isl_map_restore_space(map, space);
5787
5788 return map;
5789error:
5790 isl_map_free(map);
5791 isl_space_free(space);
5792 return NULL;
5793}
5794
5795/* Replace the space of "map" by "space", without modifying
5796 * the dimension of "map".
5797 *
5798 * If the space of "map" is identical to "space" (including the identifiers
5799 * of the input and output dimensions), then simply return the original input.
5800 */
5801__isl_give isl_map *isl_map_reset_equal_dim_space(__isl_take isl_map *map,
5802 __isl_take isl_space *space)
5803{
5804 isl_bool equal;
5805 isl_space *map_space;
5806
5807 map_space = isl_map_peek_space(map);
5808 equal = isl_space_is_equal(map_space, space);
5809 if (equal >= 0 && equal)
5810 equal = isl_space_has_equal_ids(map_space, space);
5811 if (equal < 0)
5812 goto error;
5813 if (equal) {
5814 isl_space_free(space);
5815 return map;
5816 }
5817 if (check_map_space_equal_total_dim(map, space) < 0)
5818 goto error;
5819 return isl_map_reset_space(map, space);
5820error:
5821 isl_map_free(map);
5822 isl_space_free(space);
5823 return NULL;
5824}
5825
5826__isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
5827 __isl_take isl_space *space)
5828{
5829 return set_from_map(isl_map_reset_space(set_to_map(set), space));
5830}
5831
5832/* Compute the parameter domain of the given basic set.
5833 */
5834__isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
5835{
5836 isl_bool is_params;
5837 isl_space *space;
5838 isl_size n;
5839
5840 is_params = isl_basic_set_is_params(bset);
5841 if (is_params < 0)
5842 return isl_basic_set_free(bset);
5843 if (is_params)
5844 return bset;
5845
5846 n = isl_basic_set_dim(bset, isl_dim_set);
5847 if (n < 0)
5848 return isl_basic_set_free(bset);
5849 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
5850 space = isl_basic_set_get_space(bset);
5851 space = isl_space_params(space);
5852 bset = isl_basic_set_reset_space(bset, space);
5853 return bset;
5854}
5855
5856/* Construct a zero-dimensional basic set with the given parameter domain.
5857 */
5858__isl_give isl_basic_set *isl_basic_set_from_params(
5859 __isl_take isl_basic_set *bset)
5860{
5861 isl_space *space;
5862 space = isl_basic_set_get_space(bset);
5863 space = isl_space_set_from_params(space);
5864 bset = isl_basic_set_reset_space(bset, space);
5865 return bset;
5866}
5867
5868/* Compute the parameter domain of the given set.
5869 */
5870__isl_give isl_set *isl_set_params(__isl_take isl_set *set)
5871{
5872 return isl_map_params(set_to_map(set));
5873}
5874
5875/* Construct a zero-dimensional set with the given parameter domain.
5876 */
5877__isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
5878{
5879 isl_space *space;
5880 space = isl_set_get_space(set);
5881 space = isl_space_set_from_params(space);
5882 set = isl_set_reset_space(set, space);
5883 return set;
5884}
5885
5886/* Compute the parameter domain of the given map.
5887 */
5888__isl_give isl_set *isl_map_params(__isl_take isl_map *map)
5889{
5890 isl_space *space;
5891 isl_size n_in, n_out;
5892
5893 n_in = isl_map_dim(map, isl_dim_in);
5894 n_out = isl_map_dim(map, isl_dim_out);
5895 if (n_in < 0 || n_out < 0)
5896 return isl_map_free(map);
5897 map = isl_map_project_out(map, isl_dim_in, 0, n_in);
5898 map = isl_map_project_out(map, isl_dim_out, 0, n_out);
5899 space = isl_map_get_space(map);
5900 space = isl_space_params(space);
5901 map = isl_map_reset_space(map, space);
5902 return map;
5903}
5904
5905__isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap)
5906{
5907 isl_space *space;
5908 isl_size n_out;
5909
5910 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5911 if (n_out < 0)
5912 return isl_basic_map_free(bmap);
5913 space = isl_space_domain(isl_basic_map_get_space(bmap));
5914
5915 bmap = isl_basic_map_project_out(bmap, isl_dim_out, 0, n_out);
5916
5917 return isl_basic_map_reset_space(bmap, space);
5918}
5919
5920isl_bool isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
5921{
5922 if (!bmap)
5923 return isl_bool_error;
5924 return isl_space_may_be_set(bmap->dim);
5925}
5926
5927/* Is this basic map actually a set?
5928 * Users should never call this function. Outside of isl,
5929 * the type should indicate whether something is a set or a map.
5930 */
5931isl_bool isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
5932{
5933 if (!bmap)
5934 return isl_bool_error;
5935 return isl_space_is_set(bmap->dim);
5936}
5937
5938__isl_give isl_basic_set *isl_basic_map_range(__isl_take isl_basic_map *bmap)
5939{
5940 isl_bool is_set;
5941
5942 is_set = isl_basic_map_is_set(bmap);
5943 if (is_set < 0)
5944 goto error;
5945 if (is_set)
5946 return bmap;
5947 return isl_basic_map_domain(isl_basic_map_reverse(bmap));
5948error:
5949 isl_basic_map_free(bmap);
5950 return NULL;
5951}
5952
5953__isl_give isl_basic_map *isl_basic_map_domain_map(
5954 __isl_take isl_basic_map *bmap)
5955{
5956 int i;
5957 isl_space *space;
5958 isl_basic_map *domain;
5959 isl_size nparam, n_in, n_out;
5960
5961 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5962 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5963 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5964 if (nparam < 0 || n_in < 0 || n_out < 0)
5965 return isl_basic_map_free(bmap);
5966
5967 space = isl_basic_map_get_space(bmap);
5968 space = isl_space_from_range(isl_space_domain(space));
5969 domain = isl_basic_map_universe(space);
5970
5971 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
5972 bmap = isl_basic_map_apply_range(bmap, domain);
5973 bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
5974
5975 for (i = 0; i < n_in; ++i)
5976 bmap = isl_basic_map_equate(bmap, isl_dim_in, i,
5977 isl_dim_out, i);
5978
5979 bmap = isl_basic_map_gauss(bmap, NULL);
5980 return isl_basic_map_finalize(bmap);
5981}
5982
5983__isl_give isl_basic_map *isl_basic_map_range_map(
5984 __isl_take isl_basic_map *bmap)
5985{
5986 int i;
5987 isl_space *space;
5988 isl_basic_map *range;
5989 isl_size nparam, n_in, n_out;
5990
5991 nparam = isl_basic_map_dim(bmap, isl_dim_param);
5992 n_in = isl_basic_map_dim(bmap, isl_dim_in);
5993 n_out = isl_basic_map_dim(bmap, isl_dim_out);
5994 if (nparam < 0 || n_in < 0 || n_out < 0)
5995 return isl_basic_map_free(bmap);
5996
5997 space = isl_basic_map_get_space(bmap);
5998 space = isl_space_from_range(isl_space_range(space));
5999 range = isl_basic_map_universe(space);
6000
6001 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
6002 bmap = isl_basic_map_apply_range(bmap, range);
6003 bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
6004
6005 for (i = 0; i < n_out; ++i)
6006 bmap = isl_basic_map_equate(bmap, isl_dim_in, n_in + i,
6007 isl_dim_out, i);
6008
6009 bmap = isl_basic_map_gauss(bmap, NULL);
6010 return isl_basic_map_finalize(bmap);
6011}
6012
6013int isl_map_may_be_set(__isl_keep isl_map *map)
6014{
6015 if (!map)
6016 return -1;
6017 return isl_space_may_be_set(map->dim);
6018}
6019
6020/* Is this map actually a set?
6021 * Users should never call this function. Outside of isl,
6022 * the type should indicate whether something is a set or a map.
6023 */
6024isl_bool isl_map_is_set(__isl_keep isl_map *map)
6025{
6026 if (!map)
6027 return isl_bool_error;
6028 return isl_space_is_set(map->dim);
6029}
6030
6031__isl_give isl_set *isl_map_range(__isl_take isl_map *map)
6032{
6033 isl_space *space;
6034 isl_size n_in;
6035
6036 n_in = isl_map_dim(map, isl_dim_in);
6037 if (n_in < 0)
6038 return set_from_map(isl_map_free(map));
6039 space = isl_space_range(isl_map_get_space(map));
6040
6041 map = isl_map_project_out(map, isl_dim_in, 0, n_in);
6042
6043 return set_from_map(isl_map_reset_space(map, space));
6044}
6045
6046/* Transform "map" by applying "fn_space" to its space and "fn_bmap"
6047 * to each of its basic maps.
6048 */
6049static __isl_give isl_map *isl_map_transform(__isl_take isl_map *map,
6050 __isl_give isl_space *(*fn_space)(__isl_take isl_space *space),
6051 __isl_give isl_basic_map *(*fn_bmap)(__isl_take isl_basic_map *bmap))
6052{
6053 int i;
6054 isl_space *space;
6055
6056 map = isl_map_cow(map);
6057 if (!map)
6058 return NULL;
6059
6060 for (i = 0; i < map->n; ++i) {
6061 map->p[i] = fn_bmap(map->p[i]);
6062 if (!map->p[i])
6063 return isl_map_free(map);
6064 }
6065 map = isl_map_unmark_normalized(map);
6066
6067 space = isl_map_take_space(map);
6068 space = fn_space(space);
6069 map = isl_map_restore_space(map, space);
6070
6071 return map;
6072}
6073
6074__isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
6075{
6076 return isl_map_transform(map, &isl_space_domain_map,
6077 &isl_basic_map_domain_map);
6078}
6079
6080__isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
6081{
6082 return isl_map_transform(map, &isl_space_range_map,
6083 &isl_basic_map_range_map);
6084}
6085
6086/* Given a wrapped map of the form A[B -> C],
6087 * return the map A[B -> C] -> B.
6088 */
6089__isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
6090{
6091 isl_id *id;
6092 isl_map *map;
6093
6094 if (!set)
6095 return NULL;
6096 if (!isl_set_has_tuple_id(set))
6097 return isl_map_domain_map(isl_set_unwrap(set));
6098
6099 id = isl_set_get_tuple_id(set);
6100 map = isl_map_domain_map(isl_set_unwrap(set));
6101 map = isl_map_set_tuple_id(map, isl_dim_in, id);
6102
6103 return map;
6104}
6105
6106__isl_give isl_basic_map *isl_basic_map_from_domain(
6107 __isl_take isl_basic_set *bset)
6108{
6109 return isl_basic_map_reverse(isl_basic_map_from_range(bset));
6110}
6111
6112__isl_give isl_basic_map *isl_basic_map_from_range(
6113 __isl_take isl_basic_set *bset)
6114{
6115 isl_space *space;
6116 space = isl_basic_set_get_space(bset);
6117 space = isl_space_from_range(space);
6118 bset = isl_basic_set_reset_space(bset, space);
6119 return bset_to_bmap(bset);
6120}
6121
6122/* Create a relation with the given set as range.
6123 * The domain of the created relation is a zero-dimensional
6124 * flat anonymous space.
6125 */
6126__isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
6127{
6128 isl_space *space;
6129 space = isl_set_get_space(set);
6130 space = isl_space_from_range(space);
6131 set = isl_set_reset_space(set, space);
6132 return set_to_map(set);
6133}
6134
6135/* Create a relation with the given set as domain.
6136 * The range of the created relation is a zero-dimensional
6137 * flat anonymous space.
6138 */
6139__isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
6140{
6141 return isl_map_reverse(isl_map_from_range(set));
6142}
6143
6144__isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
6145 __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
6146{
6147 return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
6148}
6149
6150__isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
6151 __isl_take isl_set *range)
6152{
6153 return isl_map_apply_range(isl_map_reverse(domain), range);
6154}
6155
6156/* Return a newly allocated isl_map with given space and flags and
6157 * room for "n" basic maps.
6158 * Make sure that all cached information is cleared.
6159 */
6160__isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *space, int n,
6161 unsigned flags)
6162{
6163 struct isl_map *map;
6164
6165 if (!space)
6166 return NULL;
6167 if (n < 0)
6168 isl_die(space->ctx, isl_error_internal,
6169 "negative number of basic maps", goto error);
6170 map = isl_calloc(space->ctx, struct isl_map,
6171 sizeof(struct isl_map) +
6172 (n - 1) * sizeof(struct isl_basic_map *));
6173 if (!map)
6174 goto error;
6175
6176 map->ctx = space->ctx;
6177 isl_ctx_ref(map->ctx);
6178 map->ref = 1;
6179 map->size = n;
6180 map->n = 0;
6181 map->dim = space;
6182 map->flags = flags;
6183 return map;
6184error:
6185 isl_space_free(space);
6186 return NULL;
6187}
6188
6189__isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *space)
6190{
6191 struct isl_basic_map *bmap;
6192 bmap = isl_basic_map_alloc_space(space, 0, 1, 0);
6193 bmap = isl_basic_map_set_to_empty(bmap);
6194 return bmap;
6195}
6196
6197__isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *space)
6198{
6199 struct isl_basic_set *bset;
6200 bset = isl_basic_set_alloc_space(space, 0, 1, 0);
6201 bset = isl_basic_set_set_to_empty(bset);
6202 return bset;
6203}
6204
6205__isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *space)
6206{
6207 struct isl_basic_map *bmap;
6208 bmap = isl_basic_map_alloc_space(space, 0, 0, 0);
6209 bmap = isl_basic_map_finalize(bmap);
6210 return bmap;
6211}
6212
6213__isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *space)
6214{
6215 struct isl_basic_set *bset;
6216 bset = isl_basic_set_alloc_space(space, 0, 0, 0);
6217 bset = isl_basic_set_finalize(bset);
6218 return bset;
6219}
6220
6221__isl_give isl_basic_map *isl_basic_map_nat_universe(
6222 __isl_take isl_space *space)
6223{
6224 int i;
6225 isl_size total = isl_space_dim(space, isl_dim_all);
6226 isl_basic_map *bmap;
6227
6228 if (total < 0)
6229 space = isl_space_free(space);
6230 bmap = isl_basic_map_alloc_space(space, 0, 0, total);
6231 for (i = 0; i < total; ++i) {
6232 int k = isl_basic_map_alloc_inequality(bmap);
6233 if (k < 0)
6234 goto error;
6235 isl_seq_clr(bmap->ineq[k], 1 + total);
6236 isl_int_set_si(bmap->ineq[k][1 + i], 1);
6237 }
6238 return bmap;
6239error:
6240 isl_basic_map_free(bmap);
6241 return NULL;
6242}
6243
6244__isl_give isl_basic_set *isl_basic_set_nat_universe(
6245 __isl_take isl_space *space)
6246{
6247 return isl_basic_map_nat_universe(space);
6248}
6249
6250__isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *space)
6251{
6252 return isl_map_from_basic_map(isl_basic_map_nat_universe(space));
6253}
6254
6255__isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *space)
6256{
6257 return isl_map_nat_universe(space);
6258}
6259
6260__isl_give isl_map *isl_map_empty(__isl_take isl_space *space)
6261{
6262 return isl_map_alloc_space(space, 0, ISL_MAP_DISJOINT);
6263}
6264
6265__isl_give isl_set *isl_set_empty(__isl_take isl_space *space)
6266{
6267 return isl_set_alloc_space(space, 0, ISL_MAP_DISJOINT);
6268}
6269
6270__isl_give isl_map *isl_map_universe(__isl_take isl_space *space)
6271{
6272 struct isl_map *map;
6273 if (!space)
6274 return NULL;
6275 map = isl_map_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6276 map = isl_map_add_basic_map(map, isl_basic_map_universe(space));
6277 return map;
6278}
6279
6280__isl_give isl_set *isl_set_universe(__isl_take isl_space *space)
6281{
6282 struct isl_set *set;
6283 if (!space)
6284 return NULL;
6285 set = isl_set_alloc_space(isl_space_copy(space), 1, ISL_MAP_DISJOINT);
6286 set = isl_set_add_basic_set(set, isl_basic_set_universe(space));
6287 return set;
6288}
6289
6290__isl_give isl_map *isl_map_dup(__isl_keep isl_map *map)
6291{
6292 int i;
6293 struct isl_map *dup;
6294
6295 if (!map)
6296 return NULL;
6297 dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
6298 for (i = 0; i < map->n; ++i)
6299 dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
6300 return dup;
6301}
6302
6303__isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
6304 __isl_take isl_basic_map *bmap)
6305{
6306 if (!bmap || !map)
6307 goto error;
6308 if (isl_basic_map_plain_is_empty(bmap)) {
6309 isl_basic_map_free(bmap);
6310 return map;
6311 }
6312 if (isl_map_basic_map_check_equal_space(map, bmap) < 0)
6313 goto error;
6314 isl_assert(map->ctx, map->n < map->size, goto error);
6315 map->p[map->n] = bmap;
6316 map->n++;
6317 map = isl_map_unmark_normalized(map);
6318 return map;
6319error:
6320 if (map)
6321 isl_map_free(map);
6322 if (bmap)
6323 isl_basic_map_free(bmap);
6324 return NULL;
6325}
6326
6327__isl_null isl_map *isl_map_free(__isl_take isl_map *map)
6328{
6329 int i;
6330
6331 if (!map)
6332 return NULL;
6333
6334 if (--map->ref > 0)
6335 return NULL;
6336
6337 clear_caches(map);
6338 isl_ctx_deref(map->ctx);
6339 for (i = 0; i < map->n; ++i)
6340 isl_basic_map_free(map->p[i]);
6341 isl_space_free(map->dim);
6342 free(map);
6343
6344 return NULL;
6345}
6346
6347static __isl_give isl_basic_map *isl_basic_map_fix_pos_si(
6348 __isl_take isl_basic_map *bmap, unsigned pos, int value)
6349{
6350 int j;
6351 isl_size total;
6352
6353 total = isl_basic_map_dim(bmap, isl_dim_all);
6354 if (total < 0)
6355 return isl_basic_map_free(bmap);
6356
6357 bmap = isl_basic_map_cow(bmap);
6358 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6359 j = isl_basic_map_alloc_equality(bmap);
6360 if (j < 0)
6361 goto error;
6362 isl_seq_clr(bmap->eq[j] + 1, total);
6363 isl_int_set_si(bmap->eq[j][pos], -1);
6364 isl_int_set_si(bmap->eq[j][0], value);
6365 bmap = isl_basic_map_simplify(bmap);
6366 return isl_basic_map_finalize(bmap);
6367error:
6368 isl_basic_map_free(bmap);
6369 return NULL;
6370}
6371
6372static __isl_give isl_basic_map *isl_basic_map_fix_pos(
6373 __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
6374{
6375 int j;
6376 isl_size total;
6377
6378 total = isl_basic_map_dim(bmap, isl_dim_all);
6379 if (total < 0)
6380 return isl_basic_map_free(bmap);
6381
6382 bmap = isl_basic_map_cow(bmap);
6383 bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
6384 j = isl_basic_map_alloc_equality(bmap);
6385 if (j < 0)
6386 goto error;
6387 isl_seq_clr(bmap->eq[j] + 1, total);
6388 isl_int_set_si(bmap->eq[j][pos], -1);
6389 isl_int_set(bmap->eq[j][0], value);
6390 bmap = isl_basic_map_simplify(bmap);
6391 return isl_basic_map_finalize(bmap);
6392error:
6393 isl_basic_map_free(bmap);
6394 return NULL;
6395}
6396
6397__isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
6398 enum isl_dim_type type, unsigned pos, int value)
6399{
6400 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6401 return isl_basic_map_free(bmap);
6402 return isl_basic_map_fix_pos_si(bmap,
6403 isl_basic_map_offset(bmap, type) + pos, value);
6404}
6405
6406__isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
6407 enum isl_dim_type type, unsigned pos, isl_int value)
6408{
6409 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6410 return isl_basic_map_free(bmap);
6411 return isl_basic_map_fix_pos(bmap,
6412 isl_basic_map_offset(bmap, type) + pos, value);
6413}
6414
6415/* Fix the value of the variable at position "pos" of type "type" of "bmap"
6416 * to be equal to "v".
6417 */
6418__isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
6419 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6420{
6421 if (!bmap || !v)
6422 goto error;
6423 if (!isl_val_is_int(v))
6424 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
6425 "expecting integer value", goto error);
6426 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6427 goto error;
6428 pos += isl_basic_map_offset(bmap, type);
6429 bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
6430 isl_val_free(v);
6431 return bmap;
6432error:
6433 isl_basic_map_free(bmap);
6434 isl_val_free(v);
6435 return NULL;
6436}
6437
6438/* Fix the value of the variable at position "pos" of type "type" of "bset"
6439 * to be equal to "v".
6440 */
6441__isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
6442 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6443{
6444 return isl_basic_map_fix_val(bset, type, pos, v);
6445}
6446
6447__isl_give isl_basic_set *isl_basic_set_fix_si(__isl_take isl_basic_set *bset,
6448 enum isl_dim_type type, unsigned pos, int value)
6449{
6450 return bset_from_bmap(isl_basic_map_fix_si(bset_to_bmap(bset),
6451 type, pos, value));
6452}
6453
6454__isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
6455 enum isl_dim_type type, unsigned pos, isl_int value)
6456{
6457 return bset_from_bmap(isl_basic_map_fix(bset_to_bmap(bset),
6458 type, pos, value));
6459}
6460
6461/* Remove the basic map at position "i" from "map" if this basic map
6462 * is (obviously) empty.
6463 */
6464static __isl_give isl_map *remove_if_empty(__isl_take isl_map *map, int i)
6465{
6466 isl_bool empty;
6467
6468 if (!map)
6469 return NULL;
6470
6471 empty = isl_basic_map_plain_is_empty(map->p[i]);
6472 if (empty < 0)
6473 return isl_map_free(map);
6474 if (!empty)
6475 return map;
6476
6477 isl_basic_map_free(map->p[i]);
6478 map->n--;
6479 if (i != map->n) {
6480 map->p[i] = map->p[map->n];
6481 map = isl_map_unmark_normalized(map);
6482
6483 }
6484
6485 return map;
6486}
6487
6488/* Perform "fn" on each basic map of "map", where we may not be holding
6489 * the only reference to "map".
6490 * In particular, "fn" should be a semantics preserving operation
6491 * that we want to apply to all copies of "map". We therefore need
6492 * to be careful not to modify "map" in a way that breaks "map"
6493 * in case anything goes wrong.
6494 */
6495__isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
6496 __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
6497{
6498 struct isl_basic_map *bmap;
6499 int i;
6500
6501 if (!map)
6502 return NULL;
6503
6504 for (i = map->n - 1; i >= 0; --i) {
6505 bmap = isl_basic_map_copy(map->p[i]);
6506 bmap = fn(bmap);
6507 if (!bmap)
6508 goto error;
6509 isl_basic_map_free(map->p[i]);
6510 map->p[i] = bmap;
6511 map = remove_if_empty(map, i);
6512 if (!map)
6513 return NULL;
6514 }
6515
6516 return map;
6517error:
6518 isl_map_free(map);
6519 return NULL;
6520}
6521
6522__isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
6523 enum isl_dim_type type, unsigned pos, int value)
6524{
6525 int i;
6526
6527 map = isl_map_cow(map);
6528 if (isl_map_check_range(map, type, pos, 1) < 0)
6529 return isl_map_free(map);
6530 for (i = map->n - 1; i >= 0; --i) {
6531 map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
6532 map = remove_if_empty(map, i);
6533 if (!map)
6534 return NULL;
6535 }
6536 map = isl_map_unmark_normalized(map);
6537 return map;
6538}
6539
6540__isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
6541 enum isl_dim_type type, unsigned pos, int value)
6542{
6543 return set_from_map(isl_map_fix_si(set_to_map(set), type, pos, value));
6544}
6545
6546__isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
6547 enum isl_dim_type type, unsigned pos, isl_int value)
6548{
6549 int i;
6550
6551 map = isl_map_cow(map);
6552 if (isl_map_check_range(map, type, pos, 1) < 0)
6553 return isl_map_free(map);
6554 for (i = 0; i < map->n; ++i) {
6555 map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
6556 if (!map->p[i])
6557 goto error;
6558 }
6559 map = isl_map_unmark_normalized(map);
6560 return map;
6561error:
6562 isl_map_free(map);
6563 return NULL;
6564}
6565
6566__isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
6567 enum isl_dim_type type, unsigned pos, isl_int value)
6568{
6569 return set_from_map(isl_map_fix(set_to_map(set), type, pos, value));
6570}
6571
6572/* Fix the value of the variable at position "pos" of type "type" of "map"
6573 * to be equal to "v".
6574 */
6575__isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
6576 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6577{
6578 int i;
6579
6580 map = isl_map_cow(map);
6581 if (!map || !v)
6582 goto error;
6583
6584 if (!isl_val_is_int(v))
6585 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6586 "expecting integer value", goto error);
6587 if (isl_map_check_range(map, type, pos, 1) < 0)
6588 goto error;
6589 for (i = map->n - 1; i >= 0; --i) {
6590 map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
6591 isl_val_copy(v));
6592 map = remove_if_empty(map, i);
6593 if (!map)
6594 goto error;
6595 }
6596 map = isl_map_unmark_normalized(map);
6597 isl_val_free(v);
6598 return map;
6599error:
6600 isl_map_free(map);
6601 isl_val_free(v);
6602 return NULL;
6603}
6604
6605/* Fix the value of the variable at position "pos" of type "type" of "set"
6606 * to be equal to "v".
6607 */
6608__isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
6609 enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
6610{
6611 return isl_map_fix_val(set, type, pos, v);
6612}
6613
6614__isl_give isl_map *isl_map_fix_input_si(__isl_take isl_map *map,
6615 unsigned input, int value)
6616{
6617 return isl_map_fix_si(map, isl_dim_in, input, value);
6618}
6619
6620__isl_give isl_set *isl_set_fix_dim_si(__isl_take isl_set *set, unsigned dim,
6621 int value)
6622{
6623 return set_from_map(isl_map_fix_si(set_to_map(set),
6624 isl_dim_set, dim, value));
6625}
6626
6627static __isl_give isl_basic_map *basic_map_bound_si(
6628 __isl_take isl_basic_map *bmap,
6629 enum isl_dim_type type, unsigned pos, int value, int upper)
6630{
6631 int j;
6632 isl_size total;
6633
6634 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6635 return isl_basic_map_free(bmap);
6636 total = isl_basic_map_dim(bmap, isl_dim_all);
6637 if (total < 0)
6638 return isl_basic_map_free(bmap);
6639 pos += isl_basic_map_offset(bmap, type);
6640 bmap = isl_basic_map_cow(bmap);
6641 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6642 j = isl_basic_map_alloc_inequality(bmap);
6643 if (j < 0)
6644 goto error;
6645 isl_seq_clr(bmap->ineq[j], 1 + total);
6646 if (upper) {
6647 isl_int_set_si(bmap->ineq[j][pos], -1);
6648 isl_int_set_si(bmap->ineq[j][0], value);
6649 } else {
6650 isl_int_set_si(bmap->ineq[j][pos], 1);
6651 isl_int_set_si(bmap->ineq[j][0], -value);
6652 }
6653 bmap = isl_basic_map_simplify(bmap);
6654 return isl_basic_map_finalize(bmap);
6655error:
6656 isl_basic_map_free(bmap);
6657 return NULL;
6658}
6659
6660__isl_give isl_basic_map *isl_basic_map_lower_bound_si(
6661 __isl_take isl_basic_map *bmap,
6662 enum isl_dim_type type, unsigned pos, int value)
6663{
6664 return basic_map_bound_si(bmap, type, pos, value, 0);
6665}
6666
6667/* Constrain the values of the given dimension to be no greater than "value".
6668 */
6669__isl_give isl_basic_map *isl_basic_map_upper_bound_si(
6670 __isl_take isl_basic_map *bmap,
6671 enum isl_dim_type type, unsigned pos, int value)
6672{
6673 return basic_map_bound_si(bmap, type, pos, value, 1);
6674}
6675
6676static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
6677 enum isl_dim_type type, unsigned pos, int value, int upper)
6678{
6679 int i;
6680
6681 map = isl_map_cow(map);
6682 if (isl_map_check_range(map, type, pos, 1) < 0)
6683 return isl_map_free(map);
6684 for (i = 0; i < map->n; ++i) {
6685 map->p[i] = basic_map_bound_si(map->p[i],
6686 type, pos, value, upper);
6687 if (!map->p[i])
6688 goto error;
6689 }
6690 map = isl_map_unmark_normalized(map);
6691 return map;
6692error:
6693 isl_map_free(map);
6694 return NULL;
6695}
6696
6697__isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
6698 enum isl_dim_type type, unsigned pos, int value)
6699{
6700 return map_bound_si(map, type, pos, value, 0);
6701}
6702
6703__isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
6704 enum isl_dim_type type, unsigned pos, int value)
6705{
6706 return map_bound_si(map, type, pos, value, 1);
6707}
6708
6709__isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
6710 enum isl_dim_type type, unsigned pos, int value)
6711{
6712 return set_from_map(isl_map_lower_bound_si(set_to_map(set),
6713 type, pos, value));
6714}
6715
6716__isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
6717 enum isl_dim_type type, unsigned pos, int value)
6718{
6719 return isl_map_upper_bound_si(set, type, pos, value);
6720}
6721
6722/* Bound the given variable of "bmap" from below (or above is "upper"
6723 * is set) to "value".
6724 */
6725static __isl_give isl_basic_map *basic_map_bound(
6726 __isl_take isl_basic_map *bmap,
6727 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6728{
6729 int j;
6730 isl_size total;
6731
6732 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
6733 return isl_basic_map_free(bmap);
6734 total = isl_basic_map_dim(bmap, isl_dim_all);
6735 if (total < 0)
6736 return isl_basic_map_free(bmap);
6737 pos += isl_basic_map_offset(bmap, type);
6738 bmap = isl_basic_map_cow(bmap);
6739 bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
6740 j = isl_basic_map_alloc_inequality(bmap);
6741 if (j < 0)
6742 goto error;
6743 isl_seq_clr(bmap->ineq[j], 1 + total);
6744 if (upper) {
6745 isl_int_set_si(bmap->ineq[j][pos], -1);
6746 isl_int_set(bmap->ineq[j][0], value);
6747 } else {
6748 isl_int_set_si(bmap->ineq[j][pos], 1);
6749 isl_int_neg(bmap->ineq[j][0], value);
6750 }
6751 bmap = isl_basic_map_simplify(bmap);
6752 return isl_basic_map_finalize(bmap);
6753error:
6754 isl_basic_map_free(bmap);
6755 return NULL;
6756}
6757
6758/* Bound the given variable of "map" from below (or above is "upper"
6759 * is set) to "value".
6760 */
6761static __isl_give isl_map *map_bound(__isl_take isl_map *map,
6762 enum isl_dim_type type, unsigned pos, isl_int value, int upper)
6763{
6764 int i;
6765
6766 map = isl_map_cow(map);
6767 if (isl_map_check_range(map, type, pos, 1) < 0)
6768 return isl_map_free(map);
6769 for (i = map->n - 1; i >= 0; --i) {
6770 map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
6771 map = remove_if_empty(map, i);
6772 if (!map)
6773 return NULL;
6774 }
6775 map = isl_map_unmark_normalized(map);
6776 return map;
6777}
6778
6779__isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
6780 enum isl_dim_type type, unsigned pos, isl_int value)
6781{
6782 return map_bound(map, type, pos, value, 0);
6783}
6784
6785__isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
6786 enum isl_dim_type type, unsigned pos, isl_int value)
6787{
6788 return map_bound(map, type, pos, value, 1);
6789}
6790
6791__isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
6792 enum isl_dim_type type, unsigned pos, isl_int value)
6793{
6794 return isl_map_lower_bound(set, type, pos, value);
6795}
6796
6797__isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
6798 enum isl_dim_type type, unsigned pos, isl_int value)
6799{
6800 return isl_map_upper_bound(set, type, pos, value);
6801}
6802
6803/* Force the values of the variable at position "pos" of type "type" of "map"
6804 * to be no smaller than "value".
6805 */
6806__isl_give isl_map *isl_map_lower_bound_val(__isl_take isl_map *map,
6807 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6808{
6809 if (!value)
6810 goto error;
6811 if (!isl_val_is_int(value))
6812 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6813 "expecting integer value", goto error);
6814 map = isl_map_lower_bound(map, type, pos, value->n);
6815 isl_val_free(value);
6816 return map;
6817error:
6818 isl_val_free(value);
6819 isl_map_free(map);
6820 return NULL;
6821}
6822
6823/* Force the values of the variable at position "pos" of type "type" of "set"
6824 * to be no smaller than "value".
6825 */
6826__isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
6827 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6828{
6829 isl_map *map;
6830
6831 map = set_to_map(set);
6832 return set_from_map(isl_map_lower_bound_val(map, type, pos, value));
6833}
6834
6835/* Force the values of the variable at position "pos" of type "type" of "map"
6836 * to be no greater than "value".
6837 */
6838__isl_give isl_map *isl_map_upper_bound_val(__isl_take isl_map *map,
6839 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6840{
6841 if (!value)
6842 goto error;
6843 if (!isl_val_is_int(value))
6844 isl_die(isl_map_get_ctx(map), isl_error_invalid,
6845 "expecting integer value", goto error);
6846 map = isl_map_upper_bound(map, type, pos, value->n);
6847 isl_val_free(value);
6848 return map;
6849error:
6850 isl_val_free(value);
6851 isl_map_free(map);
6852 return NULL;
6853}
6854
6855/* Force the values of the variable at position "pos" of type "type" of "set"
6856 * to be no greater than "value".
6857 */
6858__isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
6859 enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
6860{
6861 isl_map *map;
6862
6863 map = set_to_map(set);
6864 return set_from_map(isl_map_upper_bound_val(map, type, pos, value));
6865}
6866
6867/* If "mv" has an explicit domain, then intersect the domain of "map"
6868 * with this explicit domain.
6869 *
6870 * An isl_multi_val object never has an explicit domain,
6871 * so simply return "map".
6872 */
6873static __isl_give isl_map *isl_map_intersect_multi_val_explicit_domain(
6874 __isl_take isl_map *map, __isl_keep isl_multi_val *mv)
6875{
6876 return map;
6877}
6878
6879#undef BASE
6880#define BASE val
6881#include "isl_map_bound_templ.c"
6882
6883/* Apply "map_bound" to "set" with the corresponding value in "bound"
6884 * for each set dimension, by treating the set as a map.
6885 */
6886static __isl_give isl_set *set_bound_multi_val(__isl_take isl_set *set,
6887 __isl_take isl_multi_val *bound,
6888 __isl_give isl_map *map_bound(__isl_take isl_map *map,
6889 unsigned pos, __isl_take isl_val *value))
6890{
6891 isl_map *map;
6892
6893 map = set_to_map(set);
6894 return set_from_map(map_bound_multi_val(map, bound, map_bound));
6895}
6896
6897#undef BASE
6898#define BASE pw_aff
6899#include "isl_map_bound_templ.c"
6900
6901/* Apply "map_bound" to "set" with the corresponding value in "bound"
6902 * for each set dimension, by converting the set and the bound
6903 * to objects living in a map space.
6904 */
6905static __isl_give isl_set *set_bound_multi_pw_aff(__isl_take isl_set *set,
6906 __isl_take isl_multi_pw_aff *bound,
6907 __isl_give isl_map *set_bound(__isl_take isl_map *map,
6908 unsigned pos, __isl_take TYPE *value))
6909{
6910 isl_map *map;
6911
6912 map = isl_map_from_range(set);
6913 bound = isl_multi_pw_aff_from_range(bound);
6914 map = map_bound_multi_pw_aff(map, bound, set_bound);
6915 return isl_map_range(map);
6916}
6917
6918/* Wrapper around isl_map_lower_bound_val for use in map_bound_multi_val,
6919 * setting a bound on the given output dimension.
6920 */
6921static __isl_give isl_map *map_lower_bound_val(__isl_take isl_map *map,
6922 unsigned pos, __isl_take isl_val *v)
6923{
6924 return isl_map_lower_bound_val(map, isl_dim_out, pos, v);
6925}
6926
6927/* Force the values of the set dimensions of "set"
6928 * to be no smaller than the corresponding values in "lower".
6929 */
6930__isl_give isl_set *isl_set_lower_bound_multi_val(__isl_take isl_set *set,
6931 __isl_take isl_multi_val *lower)
6932{
6933 return set_bound_multi_val(set, lower, &map_lower_bound_val);
6934}
6935
6936/* Wrapper around isl_map_upper_bound_val for use in map_bound_multi_val,
6937 * setting a bound on the given output dimension.
6938 */
6939static __isl_give isl_map *map_upper_bound_val(__isl_take isl_map *map,
6940 unsigned pos, __isl_take isl_val *v)
6941{
6942 return isl_map_upper_bound_val(map, isl_dim_out, pos, v);
6943}
6944
6945/* Force the values of the set dimensions of "set"
6946 * to be no greater than the corresponding values in "upper".
6947 */
6948__isl_give isl_set *isl_set_upper_bound_multi_val(__isl_take isl_set *set,
6949 __isl_take isl_multi_val *upper)
6950{
6951 return set_bound_multi_val(set, upper, &map_upper_bound_val);
6952}
6953
6954/* Force the symbolic constant expression "bound"
6955 * to satisfy the relation "order" with respect to
6956 * the output variable at position "pos" of "map".
6957 *
6958 * Create an affine expression representing the output variable
6959 * in terms of the range and
6960 * compare it using "order" to "bound" (defined on the domain).
6961 * The result is a relation between elements in domain and range that
6962 * can be intersected with "map".
6963 */
6964static __isl_give isl_map *map_bound_pw_aff(__isl_take isl_map *map,
6965 unsigned pos, __isl_take isl_pw_aff *bound,
6966 __isl_give isl_map *(*order)(__isl_take isl_pw_aff *pa1,
6967 __isl_take isl_pw_aff *pa2))
6968{
6969 isl_space *space;
6970 isl_local_space *ls;
6971 isl_pw_aff *var;
6972
6973 space = isl_space_range(isl_map_get_space(map));
6974 ls = isl_local_space_from_space(space);
6975 var = isl_pw_aff_var_on_domain(ls, isl_dim_set, pos);
6976 map = isl_map_intersect(map, order(bound, var));
6977 return map;
6978}
6979
6980/* Force the values of the output variable at position "pos" of "map"
6981 * to be no smaller than the symbolic constant expression "lower".
6982 */
6983static __isl_give isl_map *map_lower_bound_pw_aff(__isl_take isl_map *map,
6984 unsigned pos, __isl_take isl_pw_aff *lower)
6985{
6986 return map_bound_pw_aff(map, pos, lower, &isl_pw_aff_le_map);
6987}
6988
6989/* Force the values of the output variable at position "pos" of "map"
6990 * to be no greater than the symbolic constant expression "upper".
6991 */
6992static __isl_give isl_map *map_upper_bound_pw_aff(__isl_take isl_map *map,
6993 unsigned pos, __isl_take isl_pw_aff *upper)
6994{
6995 return map_bound_pw_aff(map, pos, upper, &isl_pw_aff_ge_map);
6996}
6997
6998/* Force the values of the set dimensions of "set"
6999 * to be no smaller than the corresponding constant symbolic expressions
7000 * in "lower".
7001 */
7002__isl_give isl_set *isl_set_lower_bound_multi_pw_aff(__isl_take isl_set *set,
7003 __isl_take isl_multi_pw_aff *lower)
7004{
7005 return set_bound_multi_pw_aff(set, lower, &map_lower_bound_pw_aff);
7006}
7007
7008/* Force the values of the set dimensions of "set"
7009 * to be no greater than the corresponding constant symbolic expressions
7010 * in "upper".
7011 */
7012__isl_give isl_set *isl_set_upper_bound_multi_pw_aff(__isl_take isl_set *set,
7013 __isl_take isl_multi_pw_aff *upper)
7014{
7015 return set_bound_multi_pw_aff(set, upper, &map_upper_bound_pw_aff);
7016}
7017
7018/* Force the values of the output dimensions of "map"
7019 * to be no smaller than the corresponding constant symbolic expressions
7020 * in "lower".
7021 */
7022__isl_give isl_map *isl_map_lower_bound_multi_pw_aff(__isl_take isl_map *map,
7023 __isl_take isl_multi_pw_aff *lower)
7024{
7025 return map_bound_multi_pw_aff(map, lower, &map_lower_bound_pw_aff);
7026}
7027
7028/* Force the values of the output dimensions of "map"
7029 * to be no greater than the corresponding constant symbolic expressions
7030 * in "upper".
7031 */
7032__isl_give isl_map *isl_map_upper_bound_multi_pw_aff(__isl_take isl_map *map,
7033 __isl_take isl_multi_pw_aff *upper)
7034{
7035 return map_bound_multi_pw_aff(map, upper, &map_upper_bound_pw_aff);
7036}
7037
7038/* Bound the given variable of "bset" from below (or above is "upper"
7039 * is set) to "value".
7040 */
7041static __isl_give isl_basic_set *isl_basic_set_bound(
7042 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7043 isl_int value, int upper)
7044{
7045 return bset_from_bmap(basic_map_bound(bset_to_bmap(bset),
7046 type, pos, value, upper));
7047}
7048
7049/* Bound the given variable of "bset" from below (or above is "upper"
7050 * is set) to "value".
7051 */
7052static __isl_give isl_basic_set *isl_basic_set_bound_val(
7053 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7054 __isl_take isl_val *value, int upper)
7055{
7056 if (!value)
7057 goto error;
7058 if (!isl_val_is_int(value))
7059 isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
7060 "expecting integer value", goto error);
7061 bset = isl_basic_set_bound(bset, type, pos, value->n, upper);
7062 isl_val_free(value);
7063 return bset;
7064error:
7065 isl_val_free(value);
7066 isl_basic_set_free(bset);
7067 return NULL;
7068}
7069
7070/* Bound the given variable of "bset" from below to "value".
7071 */
7072__isl_give isl_basic_set *isl_basic_set_lower_bound_val(
7073 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7074 __isl_take isl_val *value)
7075{
7076 return isl_basic_set_bound_val(bset, type, pos, value, 0);
7077}
7078
7079/* Bound the given variable of "bset" from above to "value".
7080 */
7081__isl_give isl_basic_set *isl_basic_set_upper_bound_val(
7082 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned pos,
7083 __isl_take isl_val *value)
7084{
7085 return isl_basic_set_bound_val(bset, type, pos, value, 1);
7086}
7087
7088__isl_give isl_map *isl_map_reverse(__isl_take isl_map *map)
7089{
7090 return isl_map_transform(map, &isl_space_reverse,
7091 &isl_basic_map_reverse);
7092}
7093
7094/* Given a map A -> (B -> C), return the corresponding map A -> (C -> B).
7095 */
7096__isl_give isl_map *isl_map_range_reverse(__isl_take isl_map *map)
7097{
7098 return isl_map_transform(map, &isl_space_range_reverse,
7099 &isl_basic_map_range_reverse);
7100}
7101
7102#undef TYPE
7103#define TYPE isl_pw_multi_aff
7104#undef SUFFIX
7105#define SUFFIX _pw_multi_aff
7106#undef EMPTY
7107#define EMPTY isl_pw_multi_aff_empty
7108#undef ADD
7109#define ADD isl_pw_multi_aff_union_add
7110#include "isl_map_lexopt_templ.c"
7111
7112/* Given a map "map", compute the lexicographically minimal
7113 * (or maximal) image element for each domain element in dom,
7114 * in the form of an isl_pw_multi_aff.
7115 * If "empty" is not NULL, then set *empty to those elements in dom that
7116 * do not have an image element.
7117 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7118 * should be computed over the domain of "map". "empty" is also NULL
7119 * in this case.
7120 *
7121 * We first compute the lexicographically minimal or maximal element
7122 * in the first basic map. This results in a partial solution "res"
7123 * and a subset "todo" of dom that still need to be handled.
7124 * We then consider each of the remaining maps in "map" and successively
7125 * update both "res" and "todo".
7126 * If "empty" is NULL, then the todo sets are not needed and therefore
7127 * also not computed.
7128 */
7129static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
7130 __isl_take isl_map *map, __isl_take isl_set *dom,
7131 __isl_give isl_set **empty, unsigned flags)
7132{
7133 int i;
7134 int full;
7135 isl_pw_multi_aff *res;
7136 isl_set *todo;
7137
7138 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7139 if (!map || (!full && !dom))
7140 goto error;
7141
7142 if (isl_map_plain_is_empty(map)) {
7143 if (empty)
7144 *empty = dom;
7145 else
7146 isl_set_free(dom);
7147 return isl_pw_multi_aff_from_map(map);
7148 }
7149
7150 res = basic_map_partial_lexopt_pw_multi_aff(
7151 isl_basic_map_copy(map->p[0]),
7152 isl_set_copy(dom), empty, flags);
7153
7154 if (empty)
7155 todo = *empty;
7156 for (i = 1; i < map->n; ++i) {
7157 isl_pw_multi_aff *res_i;
7158
7159 res_i = basic_map_partial_lexopt_pw_multi_aff(
7160 isl_basic_map_copy(map->p[i]),
7161 isl_set_copy(dom), empty, flags);
7162
7163 if (ISL_FL_ISSET(flags, ISL_OPT_MAX))
7164 res = isl_pw_multi_aff_union_lexmax(res, res_i);
7165 else
7166 res = isl_pw_multi_aff_union_lexmin(res, res_i);
7167
7168 if (empty)
7169 todo = isl_set_intersect(todo, *empty);
7170 }
7171
7172 isl_set_free(dom);
7173 isl_map_free(map);
7174
7175 if (empty)
7176 *empty = todo;
7177
7178 return res;
7179error:
7180 if (empty)
7181 *empty = NULL;
7182 isl_set_free(dom);
7183 isl_map_free(map);
7184 return NULL;
7185}
7186
7187#undef TYPE
7188#define TYPE isl_map
7189#undef SUFFIX
7190#define SUFFIX
7191#undef EMPTY
7192#define EMPTY isl_map_empty
7193#undef ADD
7194#define ADD isl_map_union_disjoint
7195#include "isl_map_lexopt_templ.c"
7196
7197/* Given a map "map", compute the lexicographically minimal
7198 * (or maximal) image element for each domain element in "dom",
7199 * in the form of an isl_map.
7200 * If "empty" is not NULL, then set *empty to those elements in "dom" that
7201 * do not have an image element.
7202 * If "flags" includes ISL_OPT_FULL, then "dom" is NULL and the optimum
7203 * should be computed over the domain of "map". "empty" is also NULL
7204 * in this case.
7205 *
7206 * If the input consists of more than one disjunct, then first
7207 * compute the desired result in the form of an isl_pw_multi_aff and
7208 * then convert that into an isl_map.
7209 *
7210 * This function used to have an explicit implementation in terms
7211 * of isl_maps, but it would continually intersect the domains of
7212 * partial results with the complement of the domain of the next
7213 * partial solution, potentially leading to an explosion in the number
7214 * of disjuncts if there are several disjuncts in the input.
7215 * An even earlier implementation of this function would look for
7216 * better results in the domain of the partial result and for extra
7217 * results in the complement of this domain, which would lead to
7218 * even more splintering.
7219 */
7220static __isl_give isl_map *isl_map_partial_lexopt_aligned(
7221 __isl_take isl_map *map, __isl_take isl_set *dom,
7222 __isl_give isl_set **empty, unsigned flags)
7223{
7224 int full;
7225 struct isl_map *res;
7226 isl_pw_multi_aff *pma;
7227
7228 full = ISL_FL_ISSET(flags, ISL_OPT_FULL);
7229 if (!map || (!full && !dom))
7230 goto error;
7231
7232 if (isl_map_plain_is_empty(map)) {
7233 if (empty)
7234 *empty = dom;
7235 else
7236 isl_set_free(dom);
7237 return map;
7238 }
7239
7240 if (map->n == 1) {
7241 res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
7242 dom, empty, flags);
7243 isl_map_free(map);
7244 return res;
7245 }
7246
7247 pma = isl_map_partial_lexopt_aligned_pw_multi_aff(map, dom, empty,
7248 flags);
7249 return isl_map_from_pw_multi_aff_internal(pma);
7250error:
7251 if (empty)
7252 *empty = NULL;
7253 isl_set_free(dom);
7254 isl_map_free(map);
7255 return NULL;
7256}
7257
7258__isl_give isl_map *isl_map_partial_lexmax(
7259 __isl_take isl_map *map, __isl_take isl_set *dom,
7260 __isl_give isl_set **empty)
7261{
7262 return isl_map_partial_lexopt(map, dom, empty, ISL_OPT_MAX);
7263}
7264
7265__isl_give isl_map *isl_map_partial_lexmin(
7266 __isl_take isl_map *map, __isl_take isl_set *dom,
7267 __isl_give isl_set **empty)
7268{
7269 return isl_map_partial_lexopt(map, dom, empty, 0);
7270}
7271
7272__isl_give isl_set *isl_set_partial_lexmin(
7273 __isl_take isl_set *set, __isl_take isl_set *dom,
7274 __isl_give isl_set **empty)
7275{
7276 return set_from_map(isl_map_partial_lexmin(set_to_map(set),
7277 dom, empty));
7278}
7279
7280__isl_give isl_set *isl_set_partial_lexmax(
7281 __isl_take isl_set *set, __isl_take isl_set *dom,
7282 __isl_give isl_set **empty)
7283{
7284 return set_from_map(isl_map_partial_lexmax(set_to_map(set),
7285 dom, empty));
7286}
7287
7288/* Compute the lexicographic minimum (or maximum if "flags" includes
7289 * ISL_OPT_MAX) of "bset" over its parametric domain.
7290 */
7291__isl_give isl_set *isl_basic_set_lexopt(__isl_take isl_basic_set *bset,
7292 unsigned flags)
7293{
7294 return isl_basic_map_lexopt(bset, flags);
7295}
7296
7297__isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
7298{
7299 return isl_basic_map_lexopt(bmap, ISL_OPT_MAX);
7300}
7301
7302__isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
7303{
7304 return set_from_map(isl_basic_map_lexmin(bset_to_bmap(bset)));
7305}
7306
7307__isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
7308{
7309 return set_from_map(isl_basic_map_lexmax(bset_to_bmap(bset)));
7310}
7311
7312/* Compute the lexicographic minimum of "bset" over its parametric domain
7313 * for the purpose of quantifier elimination.
7314 * That is, find an explicit representation for all the existentially
7315 * quantified variables in "bset" by computing their lexicographic
7316 * minimum.
7317 */
7318static __isl_give isl_set *isl_basic_set_lexmin_compute_divs(
7319 __isl_take isl_basic_set *bset)
7320{
7321 return isl_basic_set_lexopt(bset, ISL_OPT_QE);
7322}
7323
7324/* Given a basic map with one output dimension, compute the minimum or
7325 * maximum of that dimension as an isl_pw_aff.
7326 *
7327 * Compute the optimum as a lexicographic optimum over the single
7328 * output dimension and extract the single isl_pw_aff from the result.
7329 */
7330static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
7331 int max)
7332{
7333 isl_pw_multi_aff *pma;
7334 isl_pw_aff *pwaff;
7335
7336 bmap = isl_basic_map_copy(bmap);
7337 pma = isl_basic_map_lexopt_pw_multi_aff(bmap, max ? ISL_OPT_MAX : 0);
7338 pwaff = isl_pw_multi_aff_get_pw_aff(pma, 0);
7339 isl_pw_multi_aff_free(pma);
7340
7341 return pwaff;
7342}
7343
7344/* Compute the minimum or maximum of the given output dimension
7345 * as a function of the parameters and the input dimensions,
7346 * but independently of the other output dimensions.
7347 *
7348 * We first project out the other output dimension and then compute
7349 * the "lexicographic" maximum in each basic map, combining the results
7350 * using isl_pw_aff_union_max.
7351 */
7352static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
7353 int max)
7354{
7355 int i;
7356 isl_pw_aff *pwaff;
7357 isl_size n_out;
7358
7359 n_out = isl_map_dim(map, isl_dim_out);
7360 if (n_out < 0)
7361 map = isl_map_free(map);
7362 map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
7363 map = isl_map_project_out(map, isl_dim_out, 0, pos);
7364 if (!map)
7365 return NULL;
7366
7367 if (map->n == 0) {
7368 isl_space *space = isl_map_get_space(map);
7369 isl_map_free(map);
7370 return isl_pw_aff_empty(space);
7371 }
7372
7373 pwaff = basic_map_dim_opt(map->p[0], max);
7374 for (i = 1; i < map->n; ++i) {
7375 isl_pw_aff *pwaff_i;
7376
7377 pwaff_i = basic_map_dim_opt(map->p[i], max);
7378 pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
7379 }
7380
7381 isl_map_free(map);
7382
7383 return pwaff;
7384}
7385
7386/* Compute the minimum of the given output dimension as a function of the
7387 * parameters and input dimensions, but independently of
7388 * the other output dimensions.
7389 */
7390__isl_give isl_pw_aff *isl_map_dim_min(__isl_take isl_map *map, int pos)
7391{
7392 return map_dim_opt(map, pos, 0);
7393}
7394
7395/* Compute the maximum of the given output dimension as a function of the
7396 * parameters and input dimensions, but independently of
7397 * the other output dimensions.
7398 */
7399__isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
7400{
7401 return map_dim_opt(map, pos, 1);
7402}
7403
7404/* Compute the minimum or maximum of the given set dimension
7405 * as a function of the parameters,
7406 * but independently of the other set dimensions.
7407 */
7408static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
7409 int max)
7410{
7411 return map_dim_opt(set, pos, max);
7412}
7413
7414/* Compute the maximum of the given set dimension as a function of the
7415 * parameters, but independently of the other set dimensions.
7416 */
7417__isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
7418{
7419 return set_dim_opt(set, pos, 1);
7420}
7421
7422/* Compute the minimum of the given set dimension as a function of the
7423 * parameters, but independently of the other set dimensions.
7424 */
7425__isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
7426{
7427 return set_dim_opt(set, pos, 0);
7428}
7429
7430/* Apply a preimage specified by "mat" on the parameters of "bset".
7431 * bset is assumed to have only parameters and divs.
7432 */
7433static __isl_give isl_basic_set *basic_set_parameter_preimage(
7434 __isl_take isl_basic_set *bset, __isl_take isl_mat *mat)
7435{
7436 isl_size nparam;
7437
7438 nparam = isl_basic_set_dim(bset, isl_dim_param);
7439 if (nparam < 0 || !mat)
7440 goto error;
7441
7442 bset->dim = isl_space_cow(bset->dim);
7443 if (!bset->dim)
7444 goto error;
7445
7446 isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
7447
7448 bset->dim->nparam = 0;
7449 bset->dim->n_out = nparam;
7450 bset = isl_basic_set_preimage(bset, mat);
7451 if (bset) {
7452 bset->dim->nparam = bset->dim->n_out;
7453 bset->dim->n_out = 0;
7454 }
7455 return bset;
7456error:
7457 isl_mat_free(mat);
7458 isl_basic_set_free(bset);
7459 return NULL;
7460}
7461
7462/* Apply a preimage specified by "mat" on the parameters of "set".
7463 * set is assumed to have only parameters and divs.
7464 */
7465static __isl_give isl_set *set_parameter_preimage(__isl_take isl_set *set,
7466 __isl_take isl_mat *mat)
7467{
7468 isl_space *space;
7469 isl_size nparam;
7470
7471 nparam = isl_set_dim(set, isl_dim_param);
7472 if (nparam < 0 || !mat)
7473 goto error;
7474
7475 if (mat->n_row != 1 + nparam)
7476 isl_die(isl_set_get_ctx(set), isl_error_internal,
7477 "unexpected number of rows", goto error);
7478
7479 space = isl_set_get_space(set);
7480 space = isl_space_move_dims(space, isl_dim_set, 0,
7481 isl_dim_param, 0, nparam);
7482 set = isl_set_reset_space(set, space);
7483 set = isl_set_preimage(set, mat);
7484 nparam = isl_set_dim(set, isl_dim_out);
7485 if (nparam < 0)
7486 set = isl_set_free(set);
7487 space = isl_set_get_space(set);
7488 space = isl_space_move_dims(space, isl_dim_param, 0,
7489 isl_dim_out, 0, nparam);
7490 set = isl_set_reset_space(set, space);
7491 return set;
7492error:
7493 isl_mat_free(mat);
7494 isl_set_free(set);
7495 return NULL;
7496}
7497
7498/* Intersect the basic set "bset" with the affine space specified by the
7499 * equalities in "eq".
7500 */
7501static __isl_give isl_basic_set *basic_set_append_equalities(
7502 __isl_take isl_basic_set *bset, __isl_take isl_mat *eq)
7503{
7504 int i, k;
7505 unsigned len;
7506
7507 if (!bset || !eq)
7508 goto error;
7509
7510 bset = isl_basic_set_extend(bset, 0, eq->n_row, 0);
7511 if (!bset)
7512 goto error;
7513
7514 len = isl_basic_set_offset(bset, isl_dim_div) + bset->extra;
7515 for (i = 0; i < eq->n_row; ++i) {
7516 k = isl_basic_set_alloc_equality(bset);
7517 if (k < 0)
7518 goto error;
7519 isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
7520 isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
7521 }
7522 isl_mat_free(eq);
7523
7524 bset = isl_basic_set_gauss(bset, NULL);
7525 bset = isl_basic_set_finalize(bset);
7526
7527 return bset;
7528error:
7529 isl_mat_free(eq);
7530 isl_basic_set_free(bset);
7531 return NULL;
7532}
7533
7534/* Intersect the set "set" with the affine space specified by the
7535 * equalities in "eq".
7536 */
7537static __isl_give isl_set *set_append_equalities(__isl_take isl_set *set,
7538 __isl_take isl_mat *eq)
7539{
7540 int i;
7541
7542 if (!set || !eq)
7543 goto error;
7544
7545 for (i = 0; i < set->n; ++i) {
7546 set->p[i] = basic_set_append_equalities(set->p[i],
7547 isl_mat_copy(eq));
7548 if (!set->p[i])
7549 goto error;
7550 }
7551 isl_mat_free(eq);
7552 return set;
7553error:
7554 isl_mat_free(eq);
7555 isl_set_free(set);
7556 return NULL;
7557}
7558
7559/* Given a basic set "bset" that only involves parameters and existentially
7560 * quantified variables, return the index of the first equality
7561 * that only involves parameters. If there is no such equality then
7562 * return bset->n_eq.
7563 *
7564 * This function assumes that isl_basic_set_gauss has been called on "bset".
7565 */
7566static int first_parameter_equality(__isl_keep isl_basic_set *bset)
7567{
7568 int i, j;
7569 isl_size nparam, n_div;
7570
7571 nparam = isl_basic_set_dim(bset, isl_dim_param);
7572 n_div = isl_basic_set_dim(bset, isl_dim_div);
7573 if (nparam < 0 || n_div < 0)
7574 return -1;
7575
7576 for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
7577 if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
7578 ++i;
7579 }
7580
7581 return i;
7582}
7583
7584/* Compute an explicit representation for the existentially quantified
7585 * variables in "bset" by computing the "minimal value" of the set
7586 * variables. Since there are no set variables, the computation of
7587 * the minimal value essentially computes an explicit representation
7588 * of the non-empty part(s) of "bset".
7589 *
7590 * The input only involves parameters and existentially quantified variables.
7591 * All equalities among parameters have been removed.
7592 *
7593 * Since the existentially quantified variables in the result are in general
7594 * going to be different from those in the input, we first replace
7595 * them by the minimal number of variables based on their equalities.
7596 * This should simplify the parametric integer programming.
7597 */
7598static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
7599{
7600 isl_morph *morph1, *morph2;
7601 isl_set *set;
7602 isl_size n;
7603
7604 if (!bset)
7605 return NULL;
7606 if (bset->n_eq == 0)
7607 return isl_basic_set_lexmin_compute_divs(bset);
7608
7609 morph1 = isl_basic_set_parameter_compression(bset);
7610 bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
7611 bset = isl_basic_set_lift(bset);
7612 morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
7613 bset = isl_morph_basic_set(morph2, bset);
7614 n = isl_basic_set_dim(bset, isl_dim_set);
7615 if (n < 0)
7616 bset = isl_basic_set_free(bset);
7617 bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
7618
7619 set = isl_basic_set_lexmin_compute_divs(bset);
7620
7621 set = isl_morph_set(isl_morph_inverse(morph1), set);
7622
7623 return set;
7624}
7625
7626/* Project the given basic set onto its parameter domain, possibly introducing
7627 * new, explicit, existential variables in the constraints.
7628 * The input has parameters and (possibly implicit) existential variables.
7629 * The output has the same parameters, but only
7630 * explicit existentially quantified variables.
7631 *
7632 * The actual projection is performed by pip, but pip doesn't seem
7633 * to like equalities very much, so we first remove the equalities
7634 * among the parameters by performing a variable compression on
7635 * the parameters. Afterward, an inverse transformation is performed
7636 * and the equalities among the parameters are inserted back in.
7637 *
7638 * The variable compression on the parameters may uncover additional
7639 * equalities that were only implicit before. We therefore check
7640 * if there are any new parameter equalities in the result and
7641 * if so recurse. The removal of parameter equalities is required
7642 * for the parameter compression performed by base_compute_divs.
7643 */
7644static __isl_give isl_set *parameter_compute_divs(
7645 __isl_take isl_basic_set *bset)
7646{
7647 int i;
7648 struct isl_mat *eq;
7649 struct isl_mat *T, *T2;
7650 struct isl_set *set;
7651 isl_size nparam;
7652
7653 bset = isl_basic_set_cow(bset);
7654 if (!bset)
7655 return NULL;
7656
7657 if (bset->n_eq == 0)
7658 return base_compute_divs(bset);
7659
7660 bset = isl_basic_set_gauss(bset, NULL);
7661 if (!bset)
7662 return NULL;
7663 if (isl_basic_set_plain_is_empty(bset))
7664 return isl_set_from_basic_set(bset);
7665
7666 i = first_parameter_equality(bset);
7667 if (i == bset->n_eq)
7668 return base_compute_divs(bset);
7669
7670 nparam = isl_basic_set_dim(bset, isl_dim_param);
7671 if (nparam < 0)
7672 return isl_set_from_basic_set(isl_basic_set_free(bset));
7673 eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
7674 0, 1 + nparam);
7675 eq = isl_mat_cow(eq);
7676 T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
7677 if (T && T->n_col == 0) {
7678 isl_mat_free(T);
7679 isl_mat_free(T2);
7680 isl_mat_free(eq);
7681 bset = isl_basic_set_set_to_empty(bset);
7682 return isl_set_from_basic_set(bset);
7683 }
7684 bset = basic_set_parameter_preimage(bset, T);
7685
7686 i = first_parameter_equality(bset);
7687 if (!bset)
7688 set = NULL;
7689 else if (i == bset->n_eq)
7690 set = base_compute_divs(bset);
7691 else
7692 set = parameter_compute_divs(bset);
7693 set = set_parameter_preimage(set, T2);
7694 set = set_append_equalities(set, eq);
7695 return set;
7696}
7697
7698/* Insert the divs from "ls" before those of "bmap".
7699 *
7700 * The number of columns is not changed, which means that the last
7701 * dimensions of "bmap" are being reintepreted as the divs from "ls".
7702 * The caller is responsible for removing the same number of dimensions
7703 * from the space of "bmap".
7704 */
7705static __isl_give isl_basic_map *insert_divs_from_local_space(
7706 __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
7707{
7708 int i;
7709 isl_size n_div;
7710 int old_n_div;
7711
7712 n_div = isl_local_space_dim(ls, isl_dim_div);
7713 if (n_div < 0)
7714 return isl_basic_map_free(bmap);
7715 if (n_div == 0)
7716 return bmap;
7717
7718 old_n_div = bmap->n_div;
7719 bmap = insert_div_rows(bmap, n_div);
7720 if (!bmap)
7721 return NULL;
7722
7723 for (i = 0; i < n_div; ++i) {
7724 isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
7725 isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
7726 }
7727
7728 return bmap;
7729}
7730
7731/* Replace the space of "bmap" by the space and divs of "ls".
7732 *
7733 * If "ls" has any divs, then we simplify the result since we may
7734 * have discovered some additional equalities that could simplify
7735 * the div expressions.
7736 */
7737static __isl_give isl_basic_map *basic_replace_space_by_local_space(
7738 __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
7739{
7740 isl_size n_div;
7741
7742 bmap = isl_basic_map_cow(bmap);
7743 n_div = isl_local_space_dim(ls, isl_dim_div);
7744 if (!bmap || n_div < 0)
7745 goto error;
7746
7747 bmap = insert_divs_from_local_space(bmap, ls);
7748 if (!bmap)
7749 goto error;
7750
7751 isl_space_free(bmap->dim);
7752 bmap->dim = isl_local_space_get_space(ls);
7753 if (!bmap->dim)
7754 goto error;
7755
7756 isl_local_space_free(ls);
7757 if (n_div > 0)
7758 bmap = isl_basic_map_simplify(bmap);
7759 bmap = isl_basic_map_finalize(bmap);
7760 return bmap;
7761error:
7762 isl_basic_map_free(bmap);
7763 isl_local_space_free(ls);
7764 return NULL;
7765}
7766
7767/* Replace the space of "map" by the space and divs of "ls".
7768 */
7769static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
7770 __isl_take isl_local_space *ls)
7771{
7772 int i;
7773
7774 map = isl_map_cow(map);
7775 if (!map || !ls)
7776 goto error;
7777
7778 for (i = 0; i < map->n; ++i) {
7779 map->p[i] = basic_replace_space_by_local_space(map->p[i],
7780 isl_local_space_copy(ls));
7781 if (!map->p[i])
7782 goto error;
7783 }
7784 isl_space_free(isl_map_take_space(map));
7785 map = isl_map_restore_space(map, isl_local_space_get_space(ls));
7786
7787 isl_local_space_free(ls);
7788 return map;
7789error:
7790 isl_local_space_free(ls);
7791 isl_map_free(map);
7792 return NULL;
7793}
7794
7795/* Compute an explicit representation for the existentially
7796 * quantified variables for which do not know any explicit representation yet.
7797 *
7798 * We first sort the existentially quantified variables so that the
7799 * existentially quantified variables for which we already have an explicit
7800 * representation are placed before those for which we do not.
7801 * The input dimensions, the output dimensions and the existentially
7802 * quantified variables for which we already have an explicit
7803 * representation are then turned into parameters.
7804 * compute_divs returns a map with the same parameters and
7805 * no input or output dimensions and the dimension specification
7806 * is reset to that of the input, including the existentially quantified
7807 * variables for which we already had an explicit representation.
7808 */
7809static __isl_give isl_map *compute_divs(__isl_take isl_basic_map *bmap)
7810{
7811 struct isl_basic_set *bset;
7812 struct isl_set *set;
7813 struct isl_map *map;
7814 isl_space *space;
7815 isl_local_space *ls;
7816 isl_size nparam;
7817 isl_size n_in;
7818 isl_size n_out;
7819 int n_known;
7820 int i;
7821
7822 bmap = isl_basic_map_sort_divs(bmap);
7823 bmap = isl_basic_map_cow(bmap);
7824 if (!bmap)
7825 return NULL;
7826
7827 n_known = isl_basic_map_first_unknown_div(bmap);
7828 nparam = isl_basic_map_dim(bmap, isl_dim_param);
7829 n_in = isl_basic_map_dim(bmap, isl_dim_in);
7830 n_out = isl_basic_map_dim(bmap, isl_dim_out);
7831 if (n_known < 0 || nparam < 0 || n_in < 0 || n_out < 0)
7832 return isl_map_from_basic_map(isl_basic_map_free(bmap));
7833
7834 space = isl_space_set_alloc(bmap->ctx,
7835 nparam + n_in + n_out + n_known, 0);
7836 if (!space)
7837 goto error;
7838
7839 ls = isl_basic_map_get_local_space(bmap);
7840 ls = isl_local_space_drop_dims(ls, isl_dim_div,
7841 n_known, bmap->n_div - n_known);
7842 if (n_known > 0) {
7843 for (i = n_known; i < bmap->n_div; ++i)
7844 swap_div(bmap, i - n_known, i);
7845 bmap->n_div -= n_known;
7846 bmap->extra -= n_known;
7847 }
7848 bmap = isl_basic_map_reset_space(bmap, space);
7849 bset = bset_from_bmap(bmap);
7850
7851 set = parameter_compute_divs(bset);
7852 map = set_to_map(set);
7853 map = replace_space_by_local_space(map, ls);
7854
7855 return map;
7856error:
7857 isl_basic_map_free(bmap);
7858 return NULL;
7859}
7860
7861/* Remove the explicit representation of local variable "div",
7862 * if there is any.
7863 */
7864__isl_give isl_basic_map *isl_basic_map_mark_div_unknown(
7865 __isl_take isl_basic_map *bmap, int div)
7866{
7867 isl_bool unknown;
7868
7869 unknown = isl_basic_map_div_is_marked_unknown(bmap, div);
7870 if (unknown < 0)
7871 return isl_basic_map_free(bmap);
7872 if (unknown)
7873 return bmap;
7874
7875 bmap = isl_basic_map_cow(bmap);
7876 if (!bmap)
7877 return NULL;
7878 isl_int_set_si(bmap->div[div][0], 0);
7879 return bmap;
7880}
7881
7882/* Is local variable "div" of "bmap" marked as not having an explicit
7883 * representation?
7884 * Note that even if "div" is not marked in this way and therefore
7885 * has an explicit representation, this representation may still
7886 * depend (indirectly) on other local variables that do not
7887 * have an explicit representation.
7888 */
7889isl_bool isl_basic_map_div_is_marked_unknown(__isl_keep isl_basic_map *bmap,
7890 int div)
7891{
7892 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
7893 return isl_bool_error;
7894 return isl_int_is_zero(bmap->div[div][0]);
7895}
7896
7897/* Return the position of the first local variable that does not
7898 * have an explicit representation.
7899 * Return the total number of local variables if they all have
7900 * an explicit representation.
7901 * Return -1 on error.
7902 */
7903int isl_basic_map_first_unknown_div(__isl_keep isl_basic_map *bmap)
7904{
7905 int i;
7906
7907 if (!bmap)
7908 return -1;
7909
7910 for (i = 0; i < bmap->n_div; ++i) {
7911 if (!isl_basic_map_div_is_known(bmap, i))
7912 return i;
7913 }
7914 return bmap->n_div;
7915}
7916
7917/* Return the position of the first local variable that does not
7918 * have an explicit representation.
7919 * Return the total number of local variables if they all have
7920 * an explicit representation.
7921 * Return -1 on error.
7922 */
7923int isl_basic_set_first_unknown_div(__isl_keep isl_basic_set *bset)
7924{
7925 return isl_basic_map_first_unknown_div(bset);
7926}
7927
7928/* Does "bmap" have an explicit representation for all local variables?
7929 */
7930isl_bool isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
7931{
7932 int first;
7933 isl_size n;
7934
7935 n = isl_basic_map_dim(bmap, isl_dim_div);
7936 first = isl_basic_map_first_unknown_div(bmap);
7937 if (n < 0 || first < 0)
7938 return isl_bool_error;
7939 return first == n;
7940}
7941
7942/* Do all basic maps in "map" have an explicit representation
7943 * for all local variables?
7944 */
7945isl_bool isl_map_divs_known(__isl_keep isl_map *map)
7946{
7947 int i;
7948
7949 if (!map)
7950 return isl_bool_error;
7951
7952 for (i = 0; i < map->n; ++i) {
7953 int known = isl_basic_map_divs_known(map->p[i]);
7954 if (known <= 0)
7955 return known;
7956 }
7957
7958 return isl_bool_true;
7959}
7960
7961/* If bmap contains any unknown divs, then compute explicit
7962 * expressions for them. However, this computation may be
7963 * quite expensive, so first try to remove divs that aren't
7964 * strictly needed.
7965 */
7966__isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap)
7967{
7968 int known;
7969 struct isl_map *map;
7970
7971 known = isl_basic_map_divs_known(bmap);
7972 if (known < 0)
7973 goto error;
7974 if (known)
7975 return isl_map_from_basic_map(bmap);
7976
7977 bmap = isl_basic_map_drop_redundant_divs(bmap);
7978
7979 known = isl_basic_map_divs_known(bmap);
7980 if (known < 0)
7981 goto error;
7982 if (known)
7983 return isl_map_from_basic_map(bmap);
7984
7985 map = compute_divs(bmap);
7986 return map;
7987error:
7988 isl_basic_map_free(bmap);
7989 return NULL;
7990}
7991
7992__isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map)
7993{
7994 int i;
7995 int known;
7996 struct isl_map *res;
7997
7998 if (!map)
7999 return NULL;
8000 if (map->n == 0)
8001 return map;
8002
8003 known = isl_map_divs_known(map);
8004 if (known < 0) {
8005 isl_map_free(map);
8006 return NULL;
8007 }
8008 if (known)
8009 return map;
8010
8011 res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
8012 for (i = 1 ; i < map->n; ++i) {
8013 struct isl_map *r2;
8014 r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
8015 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
8016 res = isl_map_union_disjoint(res, r2);
8017 else
8018 res = isl_map_union(res, r2);
8019 }
8020 isl_map_free(map);
8021
8022 return res;
8023}
8024
8025__isl_give isl_set *isl_basic_set_compute_divs(__isl_take isl_basic_set *bset)
8026{
8027 return set_from_map(isl_basic_map_compute_divs(bset_to_bmap(bset)));
8028}
8029
8030__isl_give isl_set *isl_set_compute_divs(__isl_take isl_set *set)
8031{
8032 return set_from_map(isl_map_compute_divs(set_to_map(set)));
8033}
8034
8035__isl_give isl_set *isl_map_domain(__isl_take isl_map *map)
8036{
8037 isl_space *space;
8038 isl_size n_out;
8039
8040 n_out = isl_map_dim(map, isl_dim_out);
8041 if (n_out < 0)
8042 return set_from_map(isl_map_free(map));
8043 space = isl_space_domain(isl_map_get_space(map));
8044
8045 map = isl_map_project_out(map, isl_dim_out, 0, n_out);
8046
8047 return set_from_map(isl_map_reset_space(map, space));
8048}
8049
8050/* Return the union of "map1" and "map2", where we assume for now that
8051 * "map1" and "map2" are disjoint. Note that the basic maps inside
8052 * "map1" or "map2" may not be disjoint from each other.
8053 * Also note that this function is also called from isl_map_union,
8054 * which takes care of handling the situation where "map1" and "map2"
8055 * may not be disjoint.
8056 *
8057 * If one of the inputs is empty, we can simply return the other input.
8058 * Similarly, if one of the inputs is universal, then it is equal to the union.
8059 */
8060static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
8061 __isl_take isl_map *map2)
8062{
8063 int i;
8064 unsigned flags = 0;
8065 struct isl_map *map = NULL;
8066 int is_universe;
8067
8068 if (isl_map_check_equal_space(map1, map2) < 0)
8069 goto error;
8070
8071 if (map1->n == 0) {
8072 isl_map_free(map1);
8073 return map2;
8074 }
8075 if (map2->n == 0) {
8076 isl_map_free(map2);
8077 return map1;
8078 }
8079
8080 is_universe = isl_map_plain_is_universe(map1);
8081 if (is_universe < 0)
8082 goto error;
8083 if (is_universe) {
8084 isl_map_free(map2);
8085 return map1;
8086 }
8087
8088 is_universe = isl_map_plain_is_universe(map2);
8089 if (is_universe < 0)
8090 goto error;
8091 if (is_universe) {
8092 isl_map_free(map1);
8093 return map2;
8094 }
8095
8096 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
8097 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
8098 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8099
8100 map = isl_map_alloc_space(isl_space_copy(map1->dim),
8101 map1->n + map2->n, flags);
8102 if (!map)
8103 goto error;
8104 for (i = 0; i < map1->n; ++i) {
8105 map = isl_map_add_basic_map(map,
8106 isl_basic_map_copy(map1->p[i]));
8107 if (!map)
8108 goto error;
8109 }
8110 for (i = 0; i < map2->n; ++i) {
8111 map = isl_map_add_basic_map(map,
8112 isl_basic_map_copy(map2->p[i]));
8113 if (!map)
8114 goto error;
8115 }
8116 isl_map_free(map1);
8117 isl_map_free(map2);
8118 return map;
8119error:
8120 isl_map_free(map);
8121 isl_map_free(map1);
8122 isl_map_free(map2);
8123 return NULL;
8124}
8125
8126/* Return the union of "map1" and "map2", where "map1" and "map2" are
8127 * guaranteed to be disjoint by the caller.
8128 *
8129 * Note that this functions is called from within isl_map_make_disjoint,
8130 * so we have to be careful not to touch the constraints of the inputs
8131 * in any way.
8132 */
8133__isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
8134 __isl_take isl_map *map2)
8135{
8136 isl_map_align_params_bin(&map1, &map2);
8137 return map_union_disjoint(map1, map2);
8138}
8139
8140/* Return the union of "map1" and "map2", where "map1" and "map2" may
8141 * not be disjoint.
8142 *
8143 * We currently simply call map_union_disjoint, the internal operation
8144 * of which does not really depend on the inputs being disjoint.
8145 * If the result contains more than one basic map, then we clear
8146 * the disjoint flag since the result may contain basic maps from
8147 * both inputs and these are not guaranteed to be disjoint.
8148 *
8149 * As a special case, if "map1" and "map2" are obviously equal,
8150 * then we simply return "map1".
8151 */
8152__isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
8153 __isl_take isl_map *map2)
8154{
8155 int equal;
8156
8157 if (isl_map_align_params_bin(&map1, &map2) < 0)
8158 goto error;
8159
8160 equal = isl_map_plain_is_equal(map1, map2);
8161 if (equal < 0)
8162 goto error;
8163 if (equal) {
8164 isl_map_free(map2);
8165 return map1;
8166 }
8167
8168 map1 = map_union_disjoint(map1, map2);
8169 if (!map1)
8170 return NULL;
8171 if (map1->n > 1)
8172 ISL_F_CLR(map1, ISL_MAP_DISJOINT);
8173 return map1;
8174error:
8175 isl_map_free(map1);
8176 isl_map_free(map2);
8177 return NULL;
8178}
8179
8180__isl_give isl_set *isl_set_union_disjoint(
8181 __isl_take isl_set *set1, __isl_take isl_set *set2)
8182{
8183 return set_from_map(isl_map_union_disjoint(set_to_map(set1),
8184 set_to_map(set2)));
8185}
8186
8187__isl_give isl_set *isl_set_union(__isl_take isl_set *set1,
8188 __isl_take isl_set *set2)
8189{
8190 return set_from_map(isl_map_union(set_to_map(set1), set_to_map(set2)));
8191}
8192
8193/* Apply "fn" to pairs of elements from "map" and "set" and collect
8194 * the results in a map living in "space".
8195 *
8196 * "map" and "set" are assumed to be compatible and non-NULL.
8197 */
8198static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
8199 __isl_take isl_space *space, __isl_take isl_set *set,
8200 __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
8201 __isl_take isl_basic_set *bset))
8202{
8203 unsigned flags = 0;
8204 struct isl_map *result;
8205 int i, j;
8206
8207 if (isl_set_plain_is_universe(set)) {
8208 isl_set_free(set);
8209 return isl_map_reset_equal_dim_space(map, space);
8210 }
8211
8212 if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
8213 ISL_F_ISSET(set, ISL_MAP_DISJOINT))
8214 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
8215
8216 result = isl_map_alloc_space(space, map->n * set->n, flags);
8217 for (i = 0; result && i < map->n; ++i)
8218 for (j = 0; j < set->n; ++j) {
8219 result = isl_map_add_basic_map(result,
8220 fn(isl_basic_map_copy(map->p[i]),
8221 isl_basic_set_copy(set->p[j])));
8222 if (!result)
8223 break;
8224 }
8225
8226 isl_map_free(map);
8227 isl_set_free(set);
8228 return result;
8229}
8230
8231__isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
8232 __isl_take isl_set *set)
8233{
8234 isl_bool ok;
8235 isl_space *space;
8236
8237 isl_map_align_params_set(&map, &set);
8238 ok = isl_map_compatible_range(map, set);
8239 if (ok < 0)
8240 goto error;
8241 if (!ok)
8242 isl_die(set->ctx, isl_error_invalid,
8243 "incompatible spaces", goto error);
8244
8245 space = isl_map_get_space(map);
8246 return map_intersect_set(map, space, set,
8247 &isl_basic_map_intersect_range);
8248error:
8249 isl_map_free(map);
8250 isl_set_free(set);
8251 return NULL;
8252}
8253
8254/* Intersect the domain of "map" with "set".
8255 *
8256 * If the domain dimensions of "map" do not have any identifiers,
8257 * then copy them over from "set".
8258 */
8259__isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
8260 __isl_take isl_set *set)
8261{
8262 isl_bool ok;
8263 isl_space *space;
8264
8265 isl_map_align_params_set(&map, &set);
8266 ok = isl_map_compatible_domain(map, set);
8267 if (ok < 0)
8268 goto error;
8269 if (!ok)
8270 isl_die(set->ctx, isl_error_invalid,
8271 "incompatible spaces", goto error);
8272
8273 space = isl_map_get_space(map);
8274 space = isl_space_copy_ids_if_unset(space, isl_dim_in,
8275 isl_set_peek_space(set), isl_dim_set);
8276 return map_intersect_set(map, space, set,
8277 &isl_basic_map_intersect_domain);
8278error:
8279 isl_map_free(map);
8280 isl_set_free(set);
8281 return NULL;
8282}
8283
8284#undef TYPE
8285#define TYPE isl_map
8286static
8287#include "isl_copy_tuple_id_templ.c"
8288
8289/* Data structure that specifies how isl_map_intersect_factor
8290 * should operate.
8291 *
8292 * "preserve_type" is the tuple where the factor differs from
8293 * the input map and of which the identifiers needs
8294 * to be preserved explicitly.
8295 * "other_factor" is used to extract the space of the other factor
8296 * from the space of the product ("map").
8297 * "product" is used to combine the given factor and a universe map
8298 * in the space returned by "other_factor" to produce a map
8299 * that lives in the same space as the input map.
8300 */
8301struct isl_intersect_factor_control {
8302 enum isl_dim_type preserve_type;
8303 __isl_give isl_space *(*other_factor)(__isl_take isl_space *space);
8304 __isl_give isl_map *(*product)(__isl_take isl_map *factor,
8305 __isl_take isl_map *other);
8306};
8307
8308/* Given a map "map" in some product space and a map "factor"
8309 * living in some factor space, return the intersection.
8310 *
8311 * After aligning the parameters,
8312 * the map "factor" is first extended to a map living in the same space
8313 * as "map" and then a regular intersection is computed.
8314 *
8315 * Note that the extension is computed as a product, which is anonymous
8316 * by default. If "map" has an identifier on the corresponding tuple,
8317 * then this identifier needs to be set on the product
8318 * before the intersection is computed.
8319 */
8320static __isl_give isl_map *isl_map_intersect_factor(
8321 __isl_take isl_map *map, __isl_take isl_map *factor,
8322 struct isl_intersect_factor_control *control)
8323{
8324 isl_bool equal;
8325 isl_space *space;
8326 isl_map *other, *product;
8327
8328 equal = isl_map_has_equal_params(map, factor);
8329 if (equal < 0)
8330 goto error;
8331 if (!equal) {
8332 map = isl_map_align_params(map, isl_map_get_space(factor));
8333 factor = isl_map_align_params(factor, isl_map_get_space(map));
8334 }
8335
8336 space = isl_map_get_space(map);
8337 other = isl_map_universe(control->other_factor(space));
8338 product = control->product(factor, other);
8339
8340 space = isl_map_peek_space(map);
8341 product = isl_map_copy_tuple_id(product, control->preserve_type,
8342 space, control->preserve_type);
8343 return map_intersect(map, product);
8344error:
8345 isl_map_free(map);
8346 isl_map_free(factor);
8347 return NULL;
8348}
8349
8350/* Return the domain product of "map2" and "map1".
8351 */
8352static __isl_give isl_map *isl_map_reverse_domain_product(
8353 __isl_take isl_map *map1, __isl_take isl_map *map2)
8354{
8355 return isl_map_domain_product(map2, map1);
8356}
8357
8358/* Return the range product of "map2" and "map1".
8359 */
8360static __isl_give isl_map *isl_map_reverse_range_product(
8361 __isl_take isl_map *map1, __isl_take isl_map *map2)
8362{
8363 return isl_map_range_product(map2, map1);
8364}
8365
8366/* Given a map "map" in a space [A -> B] -> C and a map "factor"
8367 * in the space A -> C, return the intersection.
8368 */
8369__isl_give isl_map *isl_map_intersect_domain_factor_domain(
8370 __isl_take isl_map *map, __isl_take isl_map *factor)
8371{
8372 struct isl_intersect_factor_control control = {
8373 .preserve_type = isl_dim_in,
8374 .other_factor = isl_space_domain_factor_range,
8375 .product = isl_map_domain_product,
8376 };
8377
8378 return isl_map_intersect_factor(map, factor, &control);
8379}
8380
8381/* Given a map "map" in a space [A -> B] -> C and a map "factor"
8382 * in the space B -> C, return the intersection.
8383 */
8384__isl_give isl_map *isl_map_intersect_domain_factor_range(
8385 __isl_take isl_map *map, __isl_take isl_map *factor)
8386{
8387 struct isl_intersect_factor_control control = {
8388 .preserve_type = isl_dim_in,
8389 .other_factor = isl_space_domain_factor_domain,
8390 .product = isl_map_reverse_domain_product,
8391 };
8392
8393 return isl_map_intersect_factor(map, factor, &control);
8394}
8395
8396/* Given a map "map" in a space A -> [B -> C] and a map "factor"
8397 * in the space A -> B, return the intersection.
8398 */
8399__isl_give isl_map *isl_map_intersect_range_factor_domain(
8400 __isl_take isl_map *map, __isl_take isl_map *factor)
8401{
8402 struct isl_intersect_factor_control control = {
8403 .preserve_type = isl_dim_out,
8404 .other_factor = isl_space_range_factor_range,
8405 .product = isl_map_range_product,
8406 };
8407
8408 return isl_map_intersect_factor(map, factor, &control);
8409}
8410
8411/* Given a map "map" in a space A -> [B -> C] and a map "factor"
8412 * in the space A -> C, return the intersection.
8413 */
8414__isl_give isl_map *isl_map_intersect_range_factor_range(
8415 __isl_take isl_map *map, __isl_take isl_map *factor)
8416{
8417 struct isl_intersect_factor_control control = {
8418 .preserve_type = isl_dim_out,
8419 .other_factor = isl_space_range_factor_domain,
8420 .product = isl_map_reverse_range_product,
8421 };
8422
8423 return isl_map_intersect_factor(map, factor, &control);
8424}
8425
8426/* Given a set "set" in a space [A -> B] and a set "domain"
8427 * in the space A, return the intersection.
8428 *
8429 * The set "domain" is first extended to a set living in the space
8430 * [A -> B] and then a regular intersection is computed.
8431 */
8432__isl_give isl_set *isl_set_intersect_factor_domain(__isl_take isl_set *set,
8433 __isl_take isl_set *domain)
8434{
8435 struct isl_intersect_factor_control control = {
8436 .preserve_type = isl_dim_set,
8437 .other_factor = isl_space_factor_range,
8438 .product = isl_map_range_product,
8439 };
8440
8441 return set_from_map(isl_map_intersect_factor(set_to_map(set),
8442 set_to_map(domain), &control));
8443}
8444
8445/* Given a set "set" in a space [A -> B] and a set "range"
8446 * in the space B, return the intersection.
8447 *
8448 * The set "range" is first extended to a set living in the space
8449 * [A -> B] and then a regular intersection is computed.
8450 */
8451__isl_give isl_set *isl_set_intersect_factor_range(__isl_take isl_set *set,
8452 __isl_take isl_set *range)
8453{
8454 struct isl_intersect_factor_control control = {
8455 .preserve_type = isl_dim_set,
8456 .other_factor = isl_space_factor_domain,
8457 .product = isl_map_reverse_range_product,
8458 };
8459
8460 return set_from_map(isl_map_intersect_factor(set_to_map(set),
8461 set_to_map(range), &control));
8462}
8463
8464__isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
8465 __isl_take isl_map *map2)
8466{
8467 if (isl_map_align_params_bin(&map1, &map2) < 0)
8468 goto error;
8469 map1 = isl_map_reverse(map1);
8470 map1 = isl_map_apply_range(map1, map2);
8471 return isl_map_reverse(map1);
8472error:
8473 isl_map_free(map1);
8474 isl_map_free(map2);
8475 return NULL;
8476}
8477
8478__isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
8479 __isl_take isl_map *map2)
8480{
8481 isl_space *space;
8482 struct isl_map *result;
8483 int i, j;
8484
8485 if (isl_map_align_params_bin(&map1, &map2) < 0)
8486 goto error;
8487
8488 space = isl_space_join(isl_space_copy(map1->dim),
8489 isl_space_copy(map2->dim));
8490
8491 result = isl_map_alloc_space(space, map1->n * map2->n, 0);
8492 if (!result)
8493 goto error;
8494 for (i = 0; i < map1->n; ++i)
8495 for (j = 0; j < map2->n; ++j) {
8496 result = isl_map_add_basic_map(result,
8497 isl_basic_map_apply_range(
8498 isl_basic_map_copy(map1->p[i]),
8499 isl_basic_map_copy(map2->p[j])));
8500 if (!result)
8501 goto error;
8502 }
8503 isl_map_free(map1);
8504 isl_map_free(map2);
8505 if (result && result->n <= 1)
8506 ISL_F_SET(result, ISL_MAP_DISJOINT);
8507 return result;
8508error:
8509 isl_map_free(map1);
8510 isl_map_free(map2);
8511 return NULL;
8512}
8513
8514/* Is "bmap" a transformation, i.e.,
8515 * does it relate elements from the same space.
8516 */
8517isl_bool isl_basic_map_is_transformation(__isl_keep isl_basic_map *bmap)
8518{
8519 isl_space *space;
8520
8521 space = isl_basic_map_peek_space(bmap);
8522 return isl_space_tuple_is_equal(space, isl_dim_in, space, isl_dim_out);
8523}
8524
8525/* Check that "bmap" is a transformation, i.e.,
8526 * that it relates elements from the same space.
8527 */
8528static isl_stat isl_basic_map_check_transformation(
8529 __isl_keep isl_basic_map *bmap)
8530{
8531 isl_bool equal;
8532
8533 equal = isl_basic_map_is_transformation(bmap);
8534 if (equal < 0)
8535 return isl_stat_error;
8536 if (!equal)
8537 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
8538 "domain and range don't match", return isl_stat_error);
8539 return isl_stat_ok;
8540}
8541
8542/*
8543 * returns range - domain
8544 */
8545__isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap)
8546{
8547 isl_space *target_space;
8548 struct isl_basic_set *bset;
8549 isl_size dim;
8550 isl_size nparam;
8551 isl_size total;
8552 int i;
8553
8554 if (isl_basic_map_check_transformation(bmap) < 0)
8555 return isl_basic_map_free(bmap);
8556 dim = isl_basic_map_dim(bmap, isl_dim_in);
8557 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8558 if (dim < 0 || nparam < 0)
8559 goto error;
8560 target_space = isl_space_domain(isl_basic_map_get_space(bmap));
8561 bmap = isl_basic_map_from_range(isl_basic_map_wrap(bmap));
8562 bmap = isl_basic_map_add_dims(bmap, isl_dim_in, dim);
8563 total = isl_basic_map_dim(bmap, isl_dim_all);
8564 if (total < 0)
8565 bmap = isl_basic_map_free(bmap);
8566 bmap = isl_basic_map_extend_constraints(bmap, dim, 0);
8567 for (i = 0; i < dim; ++i) {
8568 int j = isl_basic_map_alloc_equality(bmap);
8569 if (j < 0) {
8570 bmap = isl_basic_map_free(bmap);
8571 break;
8572 }
8573 isl_seq_clr(bmap->eq[j], 1 + total);
8574 isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
8575 isl_int_set_si(bmap->eq[j][1+nparam+dim+i], 1);
8576 isl_int_set_si(bmap->eq[j][1+nparam+2*dim+i], -1);
8577 }
8578 bset = isl_basic_map_domain(bmap);
8579 bset = isl_basic_set_reset_space(bset, target_space);
8580 return bset;
8581error:
8582 isl_basic_map_free(bmap);
8583 return NULL;
8584}
8585
8586/* Is the tuple of type "type1" of "map" the same as
8587 * the tuple of type "type2" of "space"?
8588 */
8589isl_bool isl_map_space_tuple_is_equal(__isl_keep isl_map *map,
8590 enum isl_dim_type type1, __isl_keep isl_space *space,
8591 enum isl_dim_type type2)
8592{
8593 isl_space *map_space;
8594
8595 map_space = isl_map_peek_space(map);
8596 return isl_space_tuple_is_equal(map_space, type1, space, type2);
8597}
8598
8599/* Is the tuple of type "type1" of "map1" the same as
8600 * the tuple of type "type2" of "map2"?
8601 */
8602isl_bool isl_map_tuple_is_equal(__isl_keep isl_map *map1,
8603 enum isl_dim_type type1, __isl_keep isl_map *map2,
8604 enum isl_dim_type type2)
8605{
8606 isl_space *space1, *space2;
8607
8608 space1 = isl_map_peek_space(map1);
8609 space2 = isl_map_peek_space(map2);
8610 return isl_space_tuple_is_equal(space1, type1, space2, type2);
8611}
8612
8613/* Is the space of "obj" equal to "space", ignoring parameters?
8614 */
8615isl_bool isl_map_has_space_tuples(__isl_keep isl_map *map,
8616 __isl_keep isl_space *space)
8617{
8618 isl_space *map_space;
8619
8620 map_space = isl_map_peek_space(map);
8621 return isl_space_has_equal_tuples(map_space, space);
8622}
8623
8624/* Check that "map" is a transformation, i.e.,
8625 * that it relates elements from the same space.
8626 */
8627isl_stat isl_map_check_transformation(__isl_keep isl_map *map)
8628{
8629 isl_bool equal;
8630
8631 equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
8632 if (equal < 0)
8633 return isl_stat_error;
8634 if (!equal)
8635 isl_die(isl_map_get_ctx(map), isl_error_invalid,
8636 "domain and range don't match", return isl_stat_error);
8637 return isl_stat_ok;
8638}
8639
8640/*
8641 * returns range - domain
8642 */
8643__isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
8644{
8645 int i;
8646 isl_space *space;
8647 struct isl_set *result;
8648
8649 if (isl_map_check_transformation(map) < 0)
8650 goto error;
8651 space = isl_map_get_space(map);
8652 space = isl_space_domain(space);
8653 result = isl_set_alloc_space(space, map->n, 0);
8654 if (!result)
8655 goto error;
8656 for (i = 0; i < map->n; ++i)
8657 result = isl_set_add_basic_set(result,
8658 isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
8659 isl_map_free(map);
8660 return result;
8661error:
8662 isl_map_free(map);
8663 return NULL;
8664}
8665
8666/*
8667 * returns [domain -> range] -> range - domain
8668 */
8669__isl_give isl_basic_map *isl_basic_map_deltas_map(
8670 __isl_take isl_basic_map *bmap)
8671{
8672 int i, k;
8673 isl_space *space;
8674 isl_basic_map *domain;
8675 isl_size nparam, n;
8676 isl_size total;
8677
8678 if (isl_basic_map_check_transformation(bmap) < 0)
8679 return isl_basic_map_free(bmap);
8680
8681 nparam = isl_basic_map_dim(bmap, isl_dim_param);
8682 n = isl_basic_map_dim(bmap, isl_dim_in);
8683 if (nparam < 0 || n < 0)
8684 return isl_basic_map_free(bmap);
8685
8686 space = isl_basic_map_get_space(bmap);
8687 space = isl_space_from_range(isl_space_domain(space));
8688 domain = isl_basic_map_universe(space);
8689
8690 bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
8691 bmap = isl_basic_map_apply_range(bmap, domain);
8692 bmap = isl_basic_map_extend_constraints(bmap, n, 0);
8693
8694 total = isl_basic_map_dim(bmap, isl_dim_all);
8695 if (total < 0)
8696 return isl_basic_map_free(bmap);
8697
8698 for (i = 0; i < n; ++i) {
8699 k = isl_basic_map_alloc_equality(bmap);
8700 if (k < 0)
8701 goto error;
8702 isl_seq_clr(bmap->eq[k], 1 + total);
8703 isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
8704 isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
8705 isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
8706 }
8707
8708 bmap = isl_basic_map_gauss(bmap, NULL);
8709 return isl_basic_map_finalize(bmap);
8710error:
8711 isl_basic_map_free(bmap);
8712 return NULL;
8713}
8714
8715/*
8716 * returns [domain -> range] -> range - domain
8717 */
8718__isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
8719{
8720 if (isl_map_check_transformation(map) < 0)
8721 return isl_map_free(map);
8722
8723 return isl_map_transform(map, &isl_space_range_map,
8724 &isl_basic_map_deltas_map);
8725}
8726
8727/* Return pairs of elements { x -> y } such that y - x is in "deltas".
8728 */
8729__isl_give isl_map *isl_set_translation(__isl_take isl_set *deltas)
8730{
8731 isl_space *space;
8732 isl_map *map;
8733
8734 space = isl_space_map_from_set(isl_set_get_space(deltas));
8735 map = isl_map_deltas_map(isl_map_universe(space));
8736 map = isl_map_intersect_range(map, deltas);
8737
8738 return isl_set_unwrap(isl_map_domain(map));
8739}
8740
8741__isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *space)
8742{
8743 isl_size n_in, n_out;
8744
8745 n_in = isl_space_dim(space, isl_dim_in);
8746 n_out = isl_space_dim(space, isl_dim_out);
8747 if (n_in < 0 || n_out < 0)
8748 goto error;
8749 if (n_in != n_out)
8750 isl_die(space->ctx, isl_error_invalid,
8751 "number of input and output dimensions needs to be "
8752 "the same", goto error);
8753 return isl_basic_map_equal(space, n_in);
8754error:
8755 isl_space_free(space);
8756 return NULL;
8757}
8758
8759__isl_give isl_map *isl_map_identity(__isl_take isl_space *space)
8760{
8761 return isl_map_from_basic_map(isl_basic_map_identity(space));
8762}
8763
8764__isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
8765{
8766 isl_space *space = isl_set_get_space(set);
8767 isl_map *id;
8768 id = isl_map_identity(isl_space_map_from_set(space));
8769 return isl_map_intersect_range(id, set);
8770}
8771
8772/* Construct a basic set with all set dimensions having only non-negative
8773 * values.
8774 */
8775__isl_give isl_basic_set *isl_basic_set_positive_orthant(
8776 __isl_take isl_space *space)
8777{
8778 int i;
8779 isl_size nparam;
8780 isl_size dim;
8781 isl_size total;
8782 struct isl_basic_set *bset;
8783
8784 nparam = isl_space_dim(space, isl_dim_param);
8785 dim = isl_space_dim(space, isl_dim_set);
8786 total = isl_space_dim(space, isl_dim_all);
8787 if (nparam < 0 || dim < 0 || total < 0)
8788 space = isl_space_free(space);
8789 bset = isl_basic_set_alloc_space(space, 0, 0, dim);
8790 if (!bset)
8791 return NULL;
8792 for (i = 0; i < dim; ++i) {
8793 int k = isl_basic_set_alloc_inequality(bset);
8794 if (k < 0)
8795 goto error;
8796 isl_seq_clr(bset->ineq[k], 1 + total);
8797 isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
8798 }
8799 return bset;
8800error:
8801 isl_basic_set_free(bset);
8802 return NULL;
8803}
8804
8805/* Construct the half-space x_pos >= 0.
8806 */
8807static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *space,
8808 int pos)
8809{
8810 int k;
8811 isl_size total;
8812 isl_basic_set *nonneg;
8813
8814 total = isl_space_dim(space, isl_dim_all);
8815 if (total < 0)
8816 space = isl_space_free(space);
8817 nonneg = isl_basic_set_alloc_space(space, 0, 0, 1);
8818 k = isl_basic_set_alloc_inequality(nonneg);
8819 if (k < 0)
8820 goto error;
8821 isl_seq_clr(nonneg->ineq[k], 1 + total);
8822 isl_int_set_si(nonneg->ineq[k][pos], 1);
8823
8824 return isl_basic_set_finalize(nonneg);
8825error:
8826 isl_basic_set_free(nonneg);
8827 return NULL;
8828}
8829
8830/* Construct the half-space x_pos <= -1.
8831 */
8832static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *space,
8833 int pos)
8834{
8835 int k;
8836 isl_size total;
8837 isl_basic_set *neg;
8838
8839 total = isl_space_dim(space, isl_dim_all);
8840 if (total < 0)
8841 space = isl_space_free(space);
8842 neg = isl_basic_set_alloc_space(space, 0, 0, 1);
8843 k = isl_basic_set_alloc_inequality(neg);
8844 if (k < 0)
8845 goto error;
8846 isl_seq_clr(neg->ineq[k], 1 + total);
8847 isl_int_set_si(neg->ineq[k][0], -1);
8848 isl_int_set_si(neg->ineq[k][pos], -1);
8849
8850 return isl_basic_set_finalize(neg);
8851error:
8852 isl_basic_set_free(neg);
8853 return NULL;
8854}
8855
8856__isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
8857 enum isl_dim_type type, unsigned first, unsigned n)
8858{
8859 int i;
8860 unsigned offset;
8861 isl_basic_set *nonneg;
8862 isl_basic_set *neg;
8863
8864 if (n == 0)
8865 return set;
8866
8867 if (isl_set_check_range(set, type, first, n) < 0)
8868 return isl_set_free(set);
8869
8870 offset = pos(set->dim, type);
8871 for (i = 0; i < n; ++i) {
8872 nonneg = nonneg_halfspace(isl_set_get_space(set),
8873 offset + first + i);
8874 neg = neg_halfspace(isl_set_get_space(set), offset + first + i);
8875
8876 set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
8877 }
8878
8879 return set;
8880}
8881
8882static isl_stat foreach_orthant(__isl_take isl_set *set, int *signs, int first,
8883 int len,
8884 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8885 void *user)
8886{
8887 isl_set *half;
8888
8889 if (!set)
8890 return isl_stat_error;
8891 if (isl_set_plain_is_empty(set)) {
8892 isl_set_free(set);
8893 return isl_stat_ok;
8894 }
8895 if (first == len)
8896 return fn(set, signs, user);
8897
8898 signs[first] = 1;
8899 half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
8900 1 + first));
8901 half = isl_set_intersect(half, isl_set_copy(set));
8902 if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
8903 goto error;
8904
8905 signs[first] = -1;
8906 half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
8907 1 + first));
8908 half = isl_set_intersect(half, set);
8909 return foreach_orthant(half, signs, first + 1, len, fn, user);
8910error:
8911 isl_set_free(set);
8912 return isl_stat_error;
8913}
8914
8915/* Call "fn" on the intersections of "set" with each of the orthants
8916 * (except for obviously empty intersections). The orthant is identified
8917 * by the signs array, with each entry having value 1 or -1 according
8918 * to the sign of the corresponding variable.
8919 */
8920isl_stat isl_set_foreach_orthant(__isl_keep isl_set *set,
8921 isl_stat (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
8922 void *user)
8923{
8924 isl_size nparam;
8925 isl_size nvar;
8926 int *signs;
8927 isl_stat r;
8928
8929 if (!set)
8930 return isl_stat_error;
8931 if (isl_set_plain_is_empty(set))
8932 return isl_stat_ok;
8933
8934 nparam = isl_set_dim(set, isl_dim_param);
8935 nvar = isl_set_dim(set, isl_dim_set);
8936 if (nparam < 0 || nvar < 0)
8937 return isl_stat_error;
8938
8939 signs = isl_alloc_array(set->ctx, int, nparam + nvar);
8940
8941 r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
8942 fn, user);
8943
8944 free(signs);
8945
8946 return r;
8947}
8948
8949isl_bool isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
8950{
8951 return isl_map_is_equal(set_to_map(set1), set_to_map(set2));
8952}
8953
8954isl_bool isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
8955 __isl_keep isl_basic_map *bmap2)
8956{
8957 isl_bool is_subset;
8958 struct isl_map *map1;
8959 struct isl_map *map2;
8960
8961 if (!bmap1 || !bmap2)
8962 return isl_bool_error;
8963
8964 map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
8965 map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
8966
8967 is_subset = isl_map_is_subset(map1, map2);
8968
8969 isl_map_free(map1);
8970 isl_map_free(map2);
8971
8972 return is_subset;
8973}
8974
8975isl_bool isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
8976 __isl_keep isl_basic_set *bset2)
8977{
8978 return isl_basic_map_is_subset(bset1, bset2);
8979}
8980
8981isl_bool isl_basic_map_is_equal(__isl_keep isl_basic_map *bmap1,
8982 __isl_keep isl_basic_map *bmap2)
8983{
8984 isl_bool is_subset;
8985
8986 if (!bmap1 || !bmap2)
8987 return isl_bool_error;
8988 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
8989 if (is_subset != isl_bool_true)
8990 return is_subset;
8991 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
8992 return is_subset;
8993}
8994
8995isl_bool isl_basic_set_is_equal(__isl_keep isl_basic_set *bset1,
8996 __isl_keep isl_basic_set *bset2)
8997{
8998 return isl_basic_map_is_equal(
8999 bset_to_bmap(bset1), bset_to_bmap(bset2));
9000}
9001
9002isl_bool isl_map_is_empty(__isl_keep isl_map *map)
9003{
9004 int i;
9005 int is_empty;
9006
9007 if (!map)
9008 return isl_bool_error;
9009 for (i = 0; i < map->n; ++i) {
9010 is_empty = isl_basic_map_is_empty(map->p[i]);
9011 if (is_empty < 0)
9012 return isl_bool_error;
9013 if (!is_empty)
9014 return isl_bool_false;
9015 }
9016 return isl_bool_true;
9017}
9018
9019isl_bool isl_map_plain_is_empty(__isl_keep isl_map *map)
9020{
9021 return map ? map->n == 0 : isl_bool_error;
9022}
9023
9024isl_bool isl_set_plain_is_empty(__isl_keep isl_set *set)
9025{
9026 return set ? set->n == 0 : isl_bool_error;
9027}
9028
9029isl_bool isl_set_is_empty(__isl_keep isl_set *set)
9030{
9031 return isl_map_is_empty(set_to_map(set));
9032}
9033
9034#undef TYPE
9035#define TYPE isl_basic_map
9036
9037static
9038#include "isl_type_has_equal_space_bin_templ.c"
9039#include "isl_type_check_equal_space_templ.c"
9040
9041/* Check that "bset1" and "bset2" live in the same space,
9042 * reporting an error if they do not.
9043 */
9044isl_stat isl_basic_set_check_equal_space(__isl_keep isl_basic_set *bset1,
9045 __isl_keep isl_basic_set *bset2)
9046{
9047 return isl_basic_map_check_equal_space(bset_to_bmap(bset1),
9048 bset_to_bmap(bset1));
9049}
9050
9051#undef TYPE
9052#define TYPE isl_map
9053
9054#include "isl_type_has_equal_space_bin_templ.c"
9055#include "isl_type_check_equal_space_templ.c"
9056#include "isl_type_has_space_templ.c"
9057
9058isl_bool isl_set_has_equal_space(__isl_keep isl_set *set1,
9059 __isl_keep isl_set *set2)
9060{
9061 return isl_map_has_equal_space(set_to_map(set1), set_to_map(set2));
9062}
9063
9064#undef TYPE1
9065#define TYPE1 isl_map
9066#undef TYPE2
9067#define TYPE2 isl_basic_map
9068#undef TYPE_PAIR
9069#define TYPE_PAIR isl_map_basic_map
9070
9071static
9072#include "isl_type_has_equal_space_templ.c"
9073#include "isl_type_check_equal_space_templ.c"
9074
9075/* Check that "set" and "bset" live in the same space,
9076 * reporting an error if they do not.
9077 */
9078isl_stat isl_set_basic_set_check_equal_space(__isl_keep isl_set *set,
9079 __isl_keep isl_basic_set *bset)
9080{
9081 return isl_map_basic_map_check_equal_space(set_to_map(set),
9082 bset_to_bmap(bset));
9083}
9084
9085static isl_bool map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9086{
9087 isl_bool is_subset;
9088
9089 if (!map1 || !map2)
9090 return isl_bool_error;
9091 is_subset = isl_map_is_subset(map1, map2);
9092 if (is_subset != isl_bool_true)
9093 return is_subset;
9094 is_subset = isl_map_is_subset(map2, map1);
9095 return is_subset;
9096}
9097
9098/* Is "map1" equal to "map2"?
9099 *
9100 * First check if they are obviously equal.
9101 * If not, then perform a more detailed analysis.
9102 */
9103isl_bool isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
9104{
9105 isl_bool equal;
9106
9107 equal = isl_map_plain_is_equal(map1, map2);
9108 if (equal < 0 || equal)
9109 return equal;
9110 return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
9111}
9112
9113isl_bool isl_basic_map_is_strict_subset(__isl_keep isl_basic_map *bmap1,
9114 __isl_keep isl_basic_map *bmap2)
9115{
9116 isl_bool is_subset;
9117
9118 if (!bmap1 || !bmap2)
9119 return isl_bool_error;
9120 is_subset = isl_basic_map_is_subset(bmap1, bmap2);
9121 if (is_subset != isl_bool_true)
9122 return is_subset;
9123 is_subset = isl_basic_map_is_subset(bmap2, bmap1);
9124 return isl_bool_not(is_subset);
9125}
9126
9127isl_bool isl_map_is_strict_subset(__isl_keep isl_map *map1,
9128 __isl_keep isl_map *map2)
9129{
9130 isl_bool is_subset;
9131
9132 if (!map1 || !map2)
9133 return isl_bool_error;
9134 is_subset = isl_map_is_subset(map1, map2);
9135 if (is_subset != isl_bool_true)
9136 return is_subset;
9137 is_subset = isl_map_is_subset(map2, map1);
9138 return isl_bool_not(is_subset);
9139}
9140
9141isl_bool isl_set_is_strict_subset(__isl_keep isl_set *set1,
9142 __isl_keep isl_set *set2)
9143{
9144 return isl_map_is_strict_subset(set_to_map(set1), set_to_map(set2));
9145}
9146
9147/* Is "bmap" obviously equal to the universe with the same space?
9148 *
9149 * That is, does it not have any constraints?
9150 */
9151isl_bool isl_basic_map_plain_is_universe(__isl_keep isl_basic_map *bmap)
9152{
9153 if (!bmap)
9154 return isl_bool_error;
9155 return bmap->n_eq == 0 && bmap->n_ineq == 0;
9156}
9157
9158/* Is "bset" obviously equal to the universe with the same space?
9159 */
9160isl_bool isl_basic_set_plain_is_universe(__isl_keep isl_basic_set *bset)
9161{
9162 return isl_basic_map_plain_is_universe(bset);
9163}
9164
9165/* If "c" does not involve any existentially quantified variables,
9166 * then set *univ to false and abort
9167 */
9168static isl_stat involves_divs(__isl_take isl_constraint *c, void *user)
9169{
9170 isl_bool *univ = user;
9171 isl_size n;
9172
9173 n = isl_constraint_dim(c, isl_dim_div);
9174 if (n < 0)
9175 c = isl_constraint_free(c);
9176 *univ = isl_constraint_involves_dims(c, isl_dim_div, 0, n);
9177 isl_constraint_free(c);
9178 if (*univ < 0 || !*univ)
9179 return isl_stat_error;
9180 return isl_stat_ok;
9181}
9182
9183/* Is "bmap" equal to the universe with the same space?
9184 *
9185 * First check if it is obviously equal to the universe.
9186 * If not and if there are any constraints not involving
9187 * existentially quantified variables, then it is certainly
9188 * not equal to the universe.
9189 * Otherwise, check if the universe is a subset of "bmap".
9190 */
9191isl_bool isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap)
9192{
9193 isl_size n_div;
9194 isl_bool univ;
9195 isl_basic_map *test;
9196
9197 univ = isl_basic_map_plain_is_universe(bmap);
9198 if (univ < 0 || univ)
9199 return univ;
9200 n_div = isl_basic_map_dim(bmap, isl_dim_div);
9201 if (n_div < 0)
9202 return isl_bool_error;
9203 if (n_div == 0)
9204 return isl_bool_false;
9205 univ = isl_bool_true;
9206 if (isl_basic_map_foreach_constraint(bmap, &involves_divs, &univ) < 0 &&
9207 univ)
9208 return isl_bool_error;
9209 if (univ < 0 || !univ)
9210 return univ;
9211 test = isl_basic_map_universe(isl_basic_map_get_space(bmap));
9212 univ = isl_basic_map_is_subset(test, bmap);
9213 isl_basic_map_free(test);
9214 return univ;
9215}
9216
9217/* Is "bset" equal to the universe with the same space?
9218 */
9219isl_bool isl_basic_set_is_universe(__isl_keep isl_basic_set *bset)
9220{
9221 return isl_basic_map_is_universe(bset);
9222}
9223
9224isl_bool isl_map_plain_is_universe(__isl_keep isl_map *map)
9225{
9226 int i;
9227
9228 if (!map)
9229 return isl_bool_error;
9230
9231 for (i = 0; i < map->n; ++i) {
9232 isl_bool r = isl_basic_map_plain_is_universe(map->p[i]);
9233 if (r < 0 || r)
9234 return r;
9235 }
9236
9237 return isl_bool_false;
9238}
9239
9240isl_bool isl_set_plain_is_universe(__isl_keep isl_set *set)
9241{
9242 return isl_map_plain_is_universe(set_to_map(set));
9243}
9244
9245isl_bool isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap)
9246{
9247 struct isl_basic_set *bset = NULL;
9248 struct isl_vec *sample = NULL;
9249 isl_bool empty, non_empty;
9250
9251 if (!bmap)
9252 return isl_bool_error;
9253
9254 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
9255 return isl_bool_true;
9256
9257 if (isl_basic_map_plain_is_universe(bmap))
9258 return isl_bool_false;
9259
9260 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
9261 struct isl_basic_map *copy = isl_basic_map_copy(bmap);
9262 copy = isl_basic_map_remove_redundancies(copy);
9263 empty = isl_basic_map_plain_is_empty(copy);
9264 isl_basic_map_free(copy);
9265 return empty;
9266 }
9267
9268 non_empty = isl_basic_map_plain_is_non_empty(bmap);
9269 if (non_empty < 0)
9270 return isl_bool_error;
9271 if (non_empty)
9272 return isl_bool_false;
9273 isl_vec_free(bmap->sample);
9274 bmap->sample = NULL;
9275 bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
9276 if (!bset)
9277 return isl_bool_error;
9278 sample = isl_basic_set_sample_vec(bset);
9279 if (!sample)
9280 return isl_bool_error;
9281 empty = sample->size == 0;
9282 isl_vec_free(bmap->sample);
9283 bmap->sample = sample;
9284 if (empty)
9285 ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
9286
9287 return empty;
9288}
9289
9290isl_bool isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
9291{
9292 if (!bmap)
9293 return isl_bool_error;
9294 return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
9295}
9296
9297isl_bool isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
9298{
9299 if (!bset)
9300 return isl_bool_error;
9301 return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
9302}
9303
9304/* Is "bmap" known to be non-empty?
9305 *
9306 * That is, is the cached sample still valid?
9307 */
9308isl_bool isl_basic_map_plain_is_non_empty(__isl_keep isl_basic_map *bmap)
9309{
9310 isl_size total;
9311
9312 if (!bmap)
9313 return isl_bool_error;
9314 if (!bmap->sample)
9315 return isl_bool_false;
9316 total = isl_basic_map_dim(bmap, isl_dim_all);
9317 if (total < 0)
9318 return isl_bool_error;
9319 if (bmap->sample->size != 1 + total)
9320 return isl_bool_false;
9321 return isl_basic_map_contains(bmap, bmap->sample);
9322}
9323
9324isl_bool isl_basic_set_is_empty(__isl_keep isl_basic_set *bset)
9325{
9326 return isl_basic_map_is_empty(bset_to_bmap(bset));
9327}
9328
9329__isl_give isl_map *isl_basic_map_union(__isl_take isl_basic_map *bmap1,
9330 __isl_take isl_basic_map *bmap2)
9331{
9332 struct isl_map *map;
9333
9334 if (isl_basic_map_check_equal_space(bmap1, bmap2) < 0)
9335 goto error;
9336
9337 map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
9338 if (!map)
9339 goto error;
9340 map = isl_map_add_basic_map(map, bmap1);
9341 map = isl_map_add_basic_map(map, bmap2);
9342 return map;
9343error:
9344 isl_basic_map_free(bmap1);
9345 isl_basic_map_free(bmap2);
9346 return NULL;
9347}
9348
9349__isl_give isl_set *isl_basic_set_union(__isl_take isl_basic_set *bset1,
9350 __isl_take isl_basic_set *bset2)
9351{
9352 return set_from_map(isl_basic_map_union(bset_to_bmap(bset1),
9353 bset_to_bmap(bset2)));
9354}
9355
9356/* Order divs such that any div only depends on previous divs */
9357__isl_give isl_basic_map *isl_basic_map_order_divs(
9358 __isl_take isl_basic_map *bmap)
9359{
9360 int i;
9361 isl_size off;
9362
9363 off = isl_basic_map_var_offset(bmap, isl_dim_div);
9364 if (off < 0)
9365 return isl_basic_map_free(bmap);
9366
9367 for (i = 0; i < bmap->n_div; ++i) {
9368 int pos;
9369 if (isl_int_is_zero(bmap->div[i][0]))
9370 continue;
9371 pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
9372 bmap->n_div-i);
9373 if (pos == -1)
9374 continue;
9375 if (pos == 0)
9376 isl_die(isl_basic_map_get_ctx(bmap), isl_error_internal,
9377 "integer division depends on itself",
9378 return isl_basic_map_free(bmap));
9379 bmap = isl_basic_map_swap_div(bmap, i, i + pos);
9380 if (!bmap)
9381 return NULL;
9382 --i;
9383 }
9384 return bmap;
9385}
9386
9387__isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
9388{
9389 int i;
9390
9391 if (!map)
9392 return 0;
9393
9394 for (i = 0; i < map->n; ++i) {
9395 map->p[i] = isl_basic_map_order_divs(map->p[i]);
9396 if (!map->p[i])
9397 goto error;
9398 }
9399
9400 return map;
9401error:
9402 isl_map_free(map);
9403 return NULL;
9404}
9405
9406/* Sort the local variables of "bset".
9407 */
9408__isl_give isl_basic_set *isl_basic_set_sort_divs(
9409 __isl_take isl_basic_set *bset)
9410{
9411 return bset_from_bmap(isl_basic_map_sort_divs(bset_to_bmap(bset)));
9412}
9413
9414/* Apply the expansion computed by isl_merge_divs.
9415 * The expansion itself is given by "exp" while the resulting
9416 * list of divs is given by "div".
9417 *
9418 * Move the integer divisions of "bmap" into the right position
9419 * according to "exp" and then introduce the additional integer
9420 * divisions, adding div constraints.
9421 * The moving should be done first to avoid moving coefficients
9422 * in the definitions of the extra integer divisions.
9423 */
9424__isl_give isl_basic_map *isl_basic_map_expand_divs(
9425 __isl_take isl_basic_map *bmap, __isl_take isl_mat *div, int *exp)
9426{
9427 int i, j;
9428 int n_div;
9429
9430 bmap = isl_basic_map_cow(bmap);
9431 if (!bmap || !div)
9432 goto error;
9433
9434 if (div->n_row < bmap->n_div)
9435 isl_die(isl_mat_get_ctx(div), isl_error_invalid,
9436 "not an expansion", goto error);
9437
9438 n_div = bmap->n_div;
9439 bmap = isl_basic_map_extend(bmap, div->n_row - n_div, 0,
9440 2 * (div->n_row - n_div));
9441
9442 for (i = n_div; i < div->n_row; ++i)
9443 if (isl_basic_map_alloc_div(bmap) < 0)
9444 goto error;
9445
9446 for (j = n_div - 1; j >= 0; --j) {
9447 if (exp[j] == j)
9448 break;
9449 bmap = isl_basic_map_swap_div(bmap, j, exp[j]);
9450 if (!bmap)
9451 goto error;
9452 }
9453 j = 0;
9454 for (i = 0; i < div->n_row; ++i) {
9455 if (j < n_div && exp[j] == i) {
9456 j++;
9457 } else {
9458 isl_seq_cpy(bmap->div[i], div->row[i], div->n_col);
9459 if (isl_basic_map_div_is_marked_unknown(bmap, i))
9460 continue;
9461 bmap = isl_basic_map_add_div_constraints(bmap, i);
9462 if (!bmap)
9463 goto error;
9464 }
9465 }
9466
9467 isl_mat_free(div);
9468 return bmap;
9469error:
9470 isl_basic_map_free(bmap);
9471 isl_mat_free(div);
9472 return NULL;
9473}
9474
9475/* Apply the expansion computed by isl_merge_divs.
9476 * The expansion itself is given by "exp" while the resulting
9477 * list of divs is given by "div".
9478 */
9479__isl_give isl_basic_set *isl_basic_set_expand_divs(
9480 __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
9481{
9482 return isl_basic_map_expand_divs(bset, div, exp);
9483}
9484
9485/* Look for a div in dst that corresponds to the div "div" in src.
9486 * The divs before "div" in src and dst are assumed to be the same.
9487 *
9488 * Return the position of the corresponding div in dst
9489 * if there is one. Otherwise, return a position beyond the integer divisions.
9490 * Return -1 on error.
9491 */
9492static int find_div(__isl_keep isl_basic_map *dst,
9493 __isl_keep isl_basic_map *src, unsigned div)
9494{
9495 int i;
9496 isl_size n_div;
9497 isl_size v_div;
9498
9499 v_div = isl_basic_map_var_offset(src, isl_dim_div);
9500 n_div = isl_basic_map_dim(dst, isl_dim_div);
9501 if (n_div < 0 || v_div < 0)
9502 return -1;
9503 isl_assert(dst->ctx, div <= n_div, return -1);
9504 for (i = div; i < n_div; ++i)
9505 if (isl_seq_eq(dst->div[i], src->div[div], 1+1+v_div+div) &&
9506 isl_seq_first_non_zero(dst->div[i] + 1 + 1 + v_div + div,
9507 n_div - div) == -1)
9508 return i;
9509 return n_div;
9510}
9511
9512/* Align the divs of "dst" to those of "src", adding divs from "src"
9513 * if needed. That is, make sure that the first src->n_div divs
9514 * of the result are equal to those of src.
9515 * The integer division of "src" are assumed to be ordered.
9516 *
9517 * The integer divisions are swapped into the right position
9518 * (possibly after adding them first). This may result
9519 * in the remaining integer divisions appearing in the wrong order,
9520 * i.e., with some integer division appearing before
9521 * some other integer division on which it depends.
9522 * The integer divisions therefore need to be ordered.
9523 * This will not affect the integer divisions aligned to those of "src",
9524 * since "src" is assumed to have ordered integer divisions.
9525 *
9526 * The result is not finalized as by design it will have redundant
9527 * divs if any divs from "src" were copied.
9528 */
9529__isl_give isl_basic_map *isl_basic_map_align_divs(
9530 __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
9531{
9532 int i;
9533 isl_bool known;
9534 int extended;
9535 isl_size v_div;
9536 isl_size dst_n_div;
9537
9538 if (!dst || !src)
9539 return isl_basic_map_free(dst);
9540
9541 if (src->n_div == 0)
9542 return dst;
9543
9544 known = isl_basic_map_divs_known(src);
9545 if (known < 0)
9546 return isl_basic_map_free(dst);
9547 if (!known)
9548 isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
9549 "some src divs are unknown",
9550 return isl_basic_map_free(dst));
9551
9552 v_div = isl_basic_map_var_offset(src, isl_dim_div);
9553 if (v_div < 0)
9554 return isl_basic_map_free(dst);
9555
9556 extended = 0;
9557 dst_n_div = isl_basic_map_dim(dst, isl_dim_div);
9558 if (dst_n_div < 0)
9559 dst = isl_basic_map_free(dst);
9560 for (i = 0; i < src->n_div; ++i) {
9561 int j = find_div(dst, src, i);
9562 if (j < 0)
9563 dst = isl_basic_map_free(dst);
9564 if (j == dst_n_div) {
9565 if (!extended) {
9566 int extra = src->n_div - i;
9567 dst = isl_basic_map_cow(dst);
9568 if (!dst)
9569 return isl_basic_map_free(dst);
9570 dst = isl_basic_map_extend(dst,
9571 extra, 0, 2 * extra);
9572 extended = 1;
9573 }
9574 j = isl_basic_map_alloc_div(dst);
9575 if (j < 0)
9576 return isl_basic_map_free(dst);
9577 isl_seq_cpy(dst->div[j], src->div[i], 1+1+v_div+i);
9578 isl_seq_clr(dst->div[j]+1+1+v_div+i, dst->n_div - i);
9579 dst_n_div++;
9580 dst = isl_basic_map_add_div_constraints(dst, j);
9581 if (!dst)
9582 return isl_basic_map_free(dst);
9583 }
9584 if (j != i)
9585 dst = isl_basic_map_swap_div(dst, i, j);
9586 if (!dst)
9587 return isl_basic_map_free(dst);
9588 }
9589 return isl_basic_map_order_divs(dst);
9590}
9591
9592__isl_give isl_map *isl_map_align_divs_internal(__isl_take isl_map *map)
9593{
9594 int i;
9595
9596 if (!map)
9597 return NULL;
9598 if (map->n == 0)
9599 return map;
9600 map = isl_map_compute_divs(map);
9601 map = isl_map_order_divs(map);
9602 map = isl_map_cow(map);
9603 if (!map)
9604 return NULL;
9605
9606 for (i = 1; i < map->n; ++i)
9607 map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
9608 for (i = 1; i < map->n; ++i) {
9609 map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
9610 if (!map->p[i])
9611 return isl_map_free(map);
9612 }
9613
9614 map = isl_map_unmark_normalized(map);
9615 return map;
9616}
9617
9618__isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map)
9619{
9620 return isl_map_align_divs_internal(map);
9621}
9622
9623__isl_give isl_set *isl_set_align_divs(__isl_take isl_set *set)
9624{
9625 return set_from_map(isl_map_align_divs_internal(set_to_map(set)));
9626}
9627
9628/* Align the divs of the basic maps in "map" to those
9629 * of the basic maps in "list", as well as to the other basic maps in "map".
9630 * The elements in "list" are assumed to have known divs.
9631 */
9632__isl_give isl_map *isl_map_align_divs_to_basic_map_list(
9633 __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
9634{
9635 int i;
9636 isl_size n;
9637
9638 n = isl_basic_map_list_n_basic_map(list);
9639 map = isl_map_compute_divs(map);
9640 map = isl_map_cow(map);
9641 if (!map || n < 0)
9642 return isl_map_free(map);
9643 if (map->n == 0)
9644 return map;
9645
9646 for (i = 0; i < n; ++i) {
9647 isl_basic_map *bmap;
9648
9649 bmap = isl_basic_map_list_get_basic_map(list, i);
9650 bmap = isl_basic_map_order_divs(bmap);
9651 map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
9652 isl_basic_map_free(bmap);
9653 }
9654 if (!map->p[0])
9655 return isl_map_free(map);
9656
9657 return isl_map_align_divs_internal(map);
9658}
9659
9660/* Align the divs of each element of "list" to those of "bmap".
9661 * Both "bmap" and the elements of "list" are assumed to have known divs.
9662 */
9663__isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
9664 __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
9665{
9666 int i;
9667 isl_size n;
9668
9669 n = isl_basic_map_list_n_basic_map(list);
9670 if (n < 0 || !bmap)
9671 return isl_basic_map_list_free(list);
9672
9673 for (i = 0; i < n; ++i) {
9674 isl_basic_map *bmap_i;
9675
9676 bmap_i = isl_basic_map_list_get_basic_map(list, i);
9677 bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
9678 list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
9679 }
9680
9681 return list;
9682}
9683
9684__isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
9685 __isl_take isl_map *map)
9686{
9687 isl_bool ok;
9688
9689 isl_map_align_params_set(&map, &set);
9690 ok = isl_map_compatible_domain(map, set);
9691 if (ok < 0)
9692 goto error;
9693 if (!ok)
9694 isl_die(isl_set_get_ctx(set), isl_error_invalid,
9695 "incompatible spaces", goto error);
9696 map = isl_map_intersect_domain(map, set);
9697 set = isl_map_range(map);
9698 return set;
9699error:
9700 isl_set_free(set);
9701 isl_map_free(map);
9702 return NULL;
9703}
9704
9705/* There is no need to cow as removing empty parts doesn't change
9706 * the meaning of the set.
9707 */
9708__isl_give isl_map *isl_map_remove_empty_parts(__isl_take isl_map *map)
9709{
9710 int i;
9711
9712 if (!map)
9713 return NULL;
9714
9715 for (i = map->n - 1; i >= 0; --i)
9716 map = remove_if_empty(map, i);
9717
9718 return map;
9719}
9720
9721__isl_give isl_set *isl_set_remove_empty_parts(__isl_take isl_set *set)
9722{
9723 return set_from_map(isl_map_remove_empty_parts(set_to_map(set)));
9724}
9725
9726/* Create a binary relation that maps the shared initial "pos" dimensions
9727 * of "bset1" and "bset2" to the remaining dimensions of "bset1" and "bset2".
9728 */
9729static __isl_give isl_basic_map *join_initial(__isl_keep isl_basic_set *bset1,
9730 __isl_keep isl_basic_set *bset2, int pos)
9731{
9732 isl_basic_map *bmap1;
9733 isl_basic_map *bmap2;
9734
9735 bmap1 = isl_basic_map_from_range(isl_basic_set_copy(bset1));
9736 bmap2 = isl_basic_map_from_range(isl_basic_set_copy(bset2));
9737 bmap1 = isl_basic_map_move_dims(bmap1, isl_dim_in, 0,
9738 isl_dim_out, 0, pos);
9739 bmap2 = isl_basic_map_move_dims(bmap2, isl_dim_in, 0,
9740 isl_dim_out, 0, pos);
9741 return isl_basic_map_range_product(bmap1, bmap2);
9742}
9743
9744/* Given two basic sets bset1 and bset2, compute the maximal difference
9745 * between the values of dimension pos in bset1 and those in bset2
9746 * for any common value of the parameters and dimensions preceding pos.
9747 */
9748static enum isl_lp_result basic_set_maximal_difference_at(
9749 __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
9750 int pos, isl_int *opt)
9751{
9752 isl_basic_map *bmap1;
9753 struct isl_ctx *ctx;
9754 struct isl_vec *obj;
9755 isl_size total;
9756 isl_size nparam;
9757 isl_size dim1;
9758 enum isl_lp_result res;
9759
9760 nparam = isl_basic_set_dim(bset1, isl_dim_param);
9761 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9762 if (nparam < 0 || dim1 < 0 || !bset2)
9763 return isl_lp_error;
9764
9765 bmap1 = join_initial(bset1, bset2, pos);
9766 total = isl_basic_map_dim(bmap1, isl_dim_all);
9767 if (total < 0)
9768 return isl_lp_error;
9769
9770 ctx = bmap1->ctx;
9771 obj = isl_vec_alloc(ctx, 1 + total);
9772 if (!obj)
9773 goto error;
9774 isl_seq_clr(obj->block.data, 1 + total);
9775 isl_int_set_si(obj->block.data[1+nparam+pos], 1);
9776 isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
9777 res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
9778 opt, NULL, NULL);
9779 isl_basic_map_free(bmap1);
9780 isl_vec_free(obj);
9781 return res;
9782error:
9783 isl_basic_map_free(bmap1);
9784 return isl_lp_error;
9785}
9786
9787/* Given two _disjoint_ basic sets bset1 and bset2, check whether
9788 * for any common value of the parameters and dimensions preceding pos
9789 * in both basic sets, the values of dimension pos in bset1 are
9790 * smaller or larger than those in bset2.
9791 *
9792 * Returns
9793 * 1 if bset1 follows bset2
9794 * -1 if bset1 precedes bset2
9795 * 0 if bset1 and bset2 are incomparable
9796 * -2 if some error occurred.
9797 */
9798int isl_basic_set_compare_at(__isl_keep isl_basic_set *bset1,
9799 __isl_keep isl_basic_set *bset2, int pos)
9800{
9801 isl_int opt;
9802 enum isl_lp_result res;
9803 int cmp;
9804
9805 isl_int_init(opt);
9806
9807 res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
9808
9809 if (res == isl_lp_empty)
9810 cmp = 0;
9811 else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
9812 res == isl_lp_unbounded)
9813 cmp = 1;
9814 else if (res == isl_lp_ok && isl_int_is_neg(opt))
9815 cmp = -1;
9816 else
9817 cmp = -2;
9818
9819 isl_int_clear(opt);
9820 return cmp;
9821}
9822
9823/* Given two basic sets bset1 and bset2, check whether
9824 * for any common value of the parameters and dimensions preceding pos
9825 * there is a value of dimension pos in bset1 that is larger
9826 * than a value of the same dimension in bset2.
9827 *
9828 * Return
9829 * 1 if there exists such a pair
9830 * 0 if there is no such pair, but there is a pair of equal values
9831 * -1 otherwise
9832 * -2 if some error occurred.
9833 */
9834int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
9835 __isl_keep isl_basic_set *bset2, int pos)
9836{
9837 isl_bool empty;
9838 isl_basic_map *bmap;
9839 isl_size dim1;
9840
9841 dim1 = isl_basic_set_dim(bset1, isl_dim_set);
9842 if (dim1 < 0)
9843 return -2;
9844 bmap = join_initial(bset1, bset2, pos);
9845 bmap = isl_basic_map_order_ge(bmap, isl_dim_out, 0,
9846 isl_dim_out, dim1 - pos);
9847 empty = isl_basic_map_is_empty(bmap);
9848 if (empty < 0)
9849 goto error;
9850 if (empty) {
9851 isl_basic_map_free(bmap);
9852 return -1;
9853 }
9854 bmap = isl_basic_map_order_gt(bmap, isl_dim_out, 0,
9855 isl_dim_out, dim1 - pos);
9856 empty = isl_basic_map_is_empty(bmap);
9857 if (empty < 0)
9858 goto error;
9859 isl_basic_map_free(bmap);
9860 if (empty)
9861 return 0;
9862 return 1;
9863error:
9864 isl_basic_map_free(bmap);
9865 return -2;
9866}
9867
9868/* Given two sets set1 and set2, check whether
9869 * for any common value of the parameters and dimensions preceding pos
9870 * there is a value of dimension pos in set1 that is larger
9871 * than a value of the same dimension in set2.
9872 *
9873 * Return
9874 * 1 if there exists such a pair
9875 * 0 if there is no such pair, but there is a pair of equal values
9876 * -1 otherwise
9877 * -2 if some error occurred.
9878 */
9879int isl_set_follows_at(__isl_keep isl_set *set1,
9880 __isl_keep isl_set *set2, int pos)
9881{
9882 int i, j;
9883 int follows = -1;
9884
9885 if (!set1 || !set2)
9886 return -2;
9887
9888 for (i = 0; i < set1->n; ++i)
9889 for (j = 0; j < set2->n; ++j) {
9890 int f;
9891 f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
9892 if (f == 1 || f == -2)
9893 return f;
9894 if (f > follows)
9895 follows = f;
9896 }
9897
9898 return follows;
9899}
9900
9901static isl_bool isl_basic_map_plain_has_fixed_var(
9902 __isl_keep isl_basic_map *bmap, unsigned pos, isl_int *val)
9903{
9904 int i;
9905 int d;
9906 isl_size total;
9907
9908 total = isl_basic_map_dim(bmap, isl_dim_all);
9909 if (total < 0)
9910 return isl_bool_error;
9911 for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
9912 for (; d+1 > pos; --d)
9913 if (!isl_int_is_zero(bmap->eq[i][1+d]))
9914 break;
9915 if (d != pos)
9916 continue;
9917 if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
9918 return isl_bool_false;
9919 if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
9920 return isl_bool_false;
9921 if (!isl_int_is_one(bmap->eq[i][1+d]))
9922 return isl_bool_false;
9923 if (val)
9924 isl_int_neg(*val, bmap->eq[i][0]);
9925 return isl_bool_true;
9926 }
9927 return isl_bool_false;
9928}
9929
9930static isl_bool isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
9931 unsigned pos, isl_int *val)
9932{
9933 int i;
9934 isl_int v;
9935 isl_int tmp;
9936 isl_bool fixed;
9937
9938 if (!map)
9939 return isl_bool_error;
9940 if (map->n == 0)
9941 return isl_bool_false;
9942 if (map->n == 1)
9943 return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
9944 isl_int_init(v);
9945 isl_int_init(tmp);
9946 fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
9947 for (i = 1; fixed == isl_bool_true && i < map->n; ++i) {
9948 fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
9949 if (fixed == isl_bool_true && isl_int_ne(tmp, v))
9950 fixed = isl_bool_false;
9951 }
9952 if (val)
9953 isl_int_set(*val, v);
9954 isl_int_clear(tmp);
9955 isl_int_clear(v);
9956 return fixed;
9957}
9958
9959static isl_bool isl_basic_set_plain_has_fixed_var(
9960 __isl_keep isl_basic_set *bset, unsigned pos, isl_int *val)
9961{
9962 return isl_basic_map_plain_has_fixed_var(bset_to_bmap(bset),
9963 pos, val);
9964}
9965
9966isl_bool isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
9967 enum isl_dim_type type, unsigned pos, isl_int *val)
9968{
9969 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
9970 return isl_bool_error;
9971 return isl_basic_map_plain_has_fixed_var(bmap,
9972 isl_basic_map_offset(bmap, type) - 1 + pos, val);
9973}
9974
9975/* If "bmap" obviously lies on a hyperplane where the given dimension
9976 * has a fixed value, then return that value.
9977 * Otherwise return NaN.
9978 */
9979__isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
9980 __isl_keep isl_basic_map *bmap,
9981 enum isl_dim_type type, unsigned pos)
9982{
9983 isl_ctx *ctx;
9984 isl_val *v;
9985 isl_bool fixed;
9986
9987 if (!bmap)
9988 return NULL;
9989 ctx = isl_basic_map_get_ctx(bmap);
9990 v = isl_val_alloc(ctx);
9991 if (!v)
9992 return NULL;
9993 fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
9994 if (fixed < 0)
9995 return isl_val_free(v);
9996 if (fixed) {
9997 isl_int_set_si(v->d, 1);
9998 return v;
9999 }
10000 isl_val_free(v);
10001 return isl_val_nan(ctx);
10002}
10003
10004isl_bool isl_map_plain_is_fixed(__isl_keep isl_map *map,
10005 enum isl_dim_type type, unsigned pos, isl_int *val)
10006{
10007 if (isl_map_check_range(map, type, pos, 1) < 0)
10008 return isl_bool_error;
10009 return isl_map_plain_has_fixed_var(map,
10010 map_offset(map, type) - 1 + pos, val);
10011}
10012
10013/* If "map" obviously lies on a hyperplane where the given dimension
10014 * has a fixed value, then return that value.
10015 * Otherwise return NaN.
10016 */
10017__isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
10018 enum isl_dim_type type, unsigned pos)
10019{
10020 isl_ctx *ctx;
10021 isl_val *v;
10022 isl_bool fixed;
10023
10024 if (!map)
10025 return NULL;
10026 ctx = isl_map_get_ctx(map);
10027 v = isl_val_alloc(ctx);
10028 if (!v)
10029 return NULL;
10030 fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
10031 if (fixed < 0)
10032 return isl_val_free(v);
10033 if (fixed) {
10034 isl_int_set_si(v->d, 1);
10035 return v;
10036 }
10037 isl_val_free(v);
10038 return isl_val_nan(ctx);
10039}
10040
10041/* If "set" obviously lies on a hyperplane where the given dimension
10042 * has a fixed value, then return that value.
10043 * Otherwise return NaN.
10044 */
10045__isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
10046 enum isl_dim_type type, unsigned pos)
10047{
10048 return isl_map_plain_get_val_if_fixed(set, type, pos);
10049}
10050
10051/* Return a sequence of values in the same space as "set"
10052 * that are equal to the corresponding set dimensions of "set"
10053 * for those set dimensions that obviously lie on a hyperplane
10054 * where the dimension has a fixed value.
10055 * The other elements are set to NaN.
10056 */
10057__isl_give isl_multi_val *isl_set_get_plain_multi_val_if_fixed(
10058 __isl_keep isl_set *set)
10059{
10060 int i;
10061 isl_size n;
10062 isl_space *space;
10063 isl_multi_val *mv;
10064
10065 space = isl_space_drop_all_params(isl_set_get_space(set));
10066 mv = isl_multi_val_alloc(space);
10067 n = isl_multi_val_size(mv);
10068 if (n < 0)
10069 return isl_multi_val_free(mv);
10070
10071 for (i = 0; i < n; ++i) {
10072 isl_val *v;
10073
10074 v = isl_set_plain_get_val_if_fixed(set, isl_dim_set, i);
10075 mv = isl_multi_val_set_val(mv, i, v);
10076 }
10077
10078 return mv;
10079}
10080
10081/* Check if dimension dim has fixed value and if so and if val is not NULL,
10082 * then return this fixed value in *val.
10083 */
10084isl_bool isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
10085 unsigned dim, isl_int *val)
10086{
10087 isl_size nparam;
10088
10089 nparam = isl_basic_set_dim(bset, isl_dim_param);
10090 if (nparam < 0)
10091 return isl_bool_error;
10092 return isl_basic_set_plain_has_fixed_var(bset, nparam + dim, val);
10093}
10094
10095/* Return -1 if the constraint "c1" should be sorted before "c2"
10096 * and 1 if it should be sorted after "c2".
10097 * Return 0 if the two constraints are the same (up to the constant term).
10098 *
10099 * In particular, if a constraint involves later variables than another
10100 * then it is sorted after this other constraint.
10101 * uset_gist depends on constraints without existentially quantified
10102 * variables sorting first.
10103 *
10104 * For constraints that have the same latest variable, those
10105 * with the same coefficient for this latest variable (first in absolute value
10106 * and then in actual value) are grouped together.
10107 * This is useful for detecting pairs of constraints that can
10108 * be chained in their printed representation.
10109 *
10110 * Finally, within a group, constraints are sorted according to
10111 * their coefficients (excluding the constant term).
10112 */
10113static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
10114{
10115 isl_int **c1 = (isl_int **) p1;
10116 isl_int **c2 = (isl_int **) p2;
10117 int l1, l2;
10118 unsigned size = *(unsigned *) arg;
10119 int cmp;
10120
10121 l1 = isl_seq_last_non_zero(*c1 + 1, size);
10122 l2 = isl_seq_last_non_zero(*c2 + 1, size);
10123
10124 if (l1 != l2)
10125 return l1 - l2;
10126
10127 cmp = isl_int_abs_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10128 if (cmp != 0)
10129 return cmp;
10130 cmp = isl_int_cmp((*c1)[1 + l1], (*c2)[1 + l1]);
10131 if (cmp != 0)
10132 return -cmp;
10133
10134 return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
10135}
10136
10137/* Return -1 if the constraint "c1" of "bmap" is sorted before "c2"
10138 * by isl_basic_map_sort_constraints, 1 if it is sorted after "c2"
10139 * and 0 if the two constraints are the same (up to the constant term).
10140 */
10141int isl_basic_map_constraint_cmp(__isl_keep isl_basic_map *bmap,
10142 isl_int *c1, isl_int *c2)
10143{
10144 isl_size total;
10145 unsigned size;
10146
10147 total = isl_basic_map_dim(bmap, isl_dim_all);
10148 if (total < 0)
10149 return -2;
10150 size = total;
10151 return sort_constraint_cmp(&c1, &c2, &size);
10152}
10153
10154__isl_give isl_basic_map *isl_basic_map_sort_constraints(
10155 __isl_take isl_basic_map *bmap)
10156{
10157 isl_size total;
10158 unsigned size;
10159
10160 if (!bmap)
10161 return NULL;
10162 if (bmap->n_ineq == 0)
10163 return bmap;
10164 if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_SORTED))
10165 return bmap;
10166 total = isl_basic_map_dim(bmap, isl_dim_all);
10167 if (total < 0)
10168 return isl_basic_map_free(bmap);
10169 size = total;
10170 if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
10171 &sort_constraint_cmp, &size) < 0)
10172 return isl_basic_map_free(bmap);
10173 ISL_F_SET(bmap, ISL_BASIC_MAP_SORTED);
10174 return bmap;
10175}
10176
10177__isl_give isl_basic_set *isl_basic_set_sort_constraints(
10178 __isl_take isl_basic_set *bset)
10179{
10180 isl_basic_map *bmap = bset_to_bmap(bset);
10181 return bset_from_bmap(isl_basic_map_sort_constraints(bmap));
10182}
10183
10184__isl_give isl_basic_map *isl_basic_map_normalize(
10185 __isl_take isl_basic_map *bmap)
10186{
10187 bmap = isl_basic_map_remove_redundancies(bmap);
10188 bmap = isl_basic_map_sort_constraints(bmap);
10189 return bmap;
10190}
10191int isl_basic_map_plain_cmp(__isl_keep isl_basic_map *bmap1,
10192 __isl_keep isl_basic_map *bmap2)
10193{
10194 int i, cmp;
10195 isl_size total;
10196 isl_space *space1, *space2;
10197
10198 if (!bmap1 || !bmap2)
10199 return -1;
10200
10201 if (bmap1 == bmap2)
10202 return 0;
10203 space1 = isl_basic_map_peek_space(bmap1);
10204 space2 = isl_basic_map_peek_space(bmap2);
10205 cmp = isl_space_cmp(space1, space2);
10206 if (cmp)
10207 return cmp;
10208 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
10209 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
10210 return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
10211 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
10212 ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10213 return 0;
10214 if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
10215 return 1;
10216 if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
10217 return -1;
10218 if (bmap1->n_eq != bmap2->n_eq)
10219 return bmap1->n_eq - bmap2->n_eq;
10220 if (bmap1->n_ineq != bmap2->n_ineq)
10221 return bmap1->n_ineq - bmap2->n_ineq;
10222 if (bmap1->n_div != bmap2->n_div)
10223 return bmap1->n_div - bmap2->n_div;
10224 total = isl_basic_map_dim(bmap1, isl_dim_all);
10225 if (total < 0)
10226 return -1;
10227 for (i = 0; i < bmap1->n_eq; ++i) {
10228 cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
10229 if (cmp)
10230 return cmp;
10231 }
10232 for (i = 0; i < bmap1->n_ineq; ++i) {
10233 cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
10234 if (cmp)
10235 return cmp;
10236 }
10237 for (i = 0; i < bmap1->n_div; ++i) {
10238 cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
10239 if (cmp)
10240 return cmp;
10241 }
10242 return 0;
10243}
10244
10245int isl_basic_set_plain_cmp(__isl_keep isl_basic_set *bset1,
10246 __isl_keep isl_basic_set *bset2)
10247{
10248 return isl_basic_map_plain_cmp(bset1, bset2);
10249}
10250
10251int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
10252{
10253 int i, cmp;
10254
10255 if (set1 == set2)
10256 return 0;
10257 if (set1->n != set2->n)
10258 return set1->n - set2->n;
10259
10260 for (i = 0; i < set1->n; ++i) {
10261 cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
10262 if (cmp)
10263 return cmp;
10264 }
10265
10266 return 0;
10267}
10268
10269isl_bool isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
10270 __isl_keep isl_basic_map *bmap2)
10271{
10272 if (!bmap1 || !bmap2)
10273 return isl_bool_error;
10274 return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
10275}
10276
10277isl_bool isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
10278 __isl_keep isl_basic_set *bset2)
10279{
10280 return isl_basic_map_plain_is_equal(bset_to_bmap(bset1),
10281 bset_to_bmap(bset2));
10282}
10283
10284static int qsort_bmap_cmp(const void *p1, const void *p2)
10285{
10286 isl_basic_map *bmap1 = *(isl_basic_map **) p1;
10287 isl_basic_map *bmap2 = *(isl_basic_map **) p2;
10288
10289 return isl_basic_map_plain_cmp(bmap1, bmap2);
10290}
10291
10292/* Sort the basic maps of "map" and remove duplicate basic maps.
10293 *
10294 * While removing basic maps, we make sure that the basic maps remain
10295 * sorted because isl_map_normalize expects the basic maps of the result
10296 * to be sorted.
10297 */
10298static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
10299{
10300 int i, j;
10301
10302 map = isl_map_remove_empty_parts(map);
10303 if (!map)
10304 return NULL;
10305 qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
10306 for (i = map->n - 1; i >= 1; --i) {
10307 if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
10308 continue;
10309 isl_basic_map_free(map->p[i-1]);
10310 for (j = i; j < map->n; ++j)
10311 map->p[j - 1] = map->p[j];
10312 map->n--;
10313 }
10314
10315 return map;
10316}
10317
10318/* Remove obvious duplicates among the basic maps of "map".
10319 *
10320 * Unlike isl_map_normalize, this function does not remove redundant
10321 * constraints and only removes duplicates that have exactly the same
10322 * constraints in the input. It does sort the constraints and
10323 * the basic maps to ease the detection of duplicates.
10324 *
10325 * If "map" has already been normalized or if the basic maps are
10326 * disjoint, then there can be no duplicates.
10327 */
10328__isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
10329{
10330 int i;
10331 isl_basic_map *bmap;
10332
10333 if (!map)
10334 return NULL;
10335 if (map->n <= 1)
10336 return map;
10337 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
10338 return map;
10339 for (i = 0; i < map->n; ++i) {
10340 bmap = isl_basic_map_copy(map->p[i]);
10341 bmap = isl_basic_map_sort_constraints(bmap);
10342 if (!bmap)
10343 return isl_map_free(map);
10344 isl_basic_map_free(map->p[i]);
10345 map->p[i] = bmap;
10346 }
10347
10348 map = sort_and_remove_duplicates(map);
10349 return map;
10350}
10351
10352/* We normalize in place, but if anything goes wrong we need
10353 * to return NULL, so we need to make sure we don't change the
10354 * meaning of any possible other copies of map.
10355 */
10356__isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
10357{
10358 int i;
10359 struct isl_basic_map *bmap;
10360
10361 if (!map)
10362 return NULL;
10363 if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
10364 return map;
10365 for (i = 0; i < map->n; ++i) {
10366 bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
10367 if (!bmap)
10368 goto error;
10369 isl_basic_map_free(map->p[i]);
10370 map->p[i] = bmap;
10371 }
10372
10373 map = sort_and_remove_duplicates(map);
10374 if (map)
10375 ISL_F_SET(map, ISL_MAP_NORMALIZED);
10376 return map;
10377error:
10378 isl_map_free(map);
10379 return NULL;
10380}
10381
10382__isl_give isl_set *isl_set_normalize(__isl_take isl_set *set)
10383{
10384 return set_from_map(isl_map_normalize(set_to_map(set)));
10385}
10386
10387isl_bool isl_map_plain_is_equal(__isl_keep isl_map *map1,
10388 __isl_keep isl_map *map2)
10389{
10390 int i;
10391 isl_bool equal;
10392
10393 if (!map1 || !map2)
10394 return isl_bool_error;
10395
10396 if (map1 == map2)
10397 return isl_bool_true;
10398 equal = isl_map_has_equal_space(map1, map2);
10399 if (equal < 0 || !equal)
10400 return equal;
10401
10402 map1 = isl_map_copy(map1);
10403 map2 = isl_map_copy(map2);
10404 map1 = isl_map_normalize(map1);
10405 map2 = isl_map_normalize(map2);
10406 if (!map1 || !map2)
10407 goto error;
10408 equal = map1->n == map2->n;
10409 for (i = 0; equal && i < map1->n; ++i) {
10410 equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
10411 if (equal < 0)
10412 goto error;
10413 }
10414 isl_map_free(map1);
10415 isl_map_free(map2);
10416 return equal;
10417error:
10418 isl_map_free(map1);
10419 isl_map_free(map2);
10420 return isl_bool_error;
10421}
10422
10423isl_bool isl_set_plain_is_equal(__isl_keep isl_set *set1,
10424 __isl_keep isl_set *set2)
10425{
10426 return isl_map_plain_is_equal(set_to_map(set1), set_to_map(set2));
10427}
10428
10429/* Return the basic maps in "map" as a list.
10430 */
10431__isl_give isl_basic_map_list *isl_map_get_basic_map_list(
10432 __isl_keep isl_map *map)
10433{
10434 int i;
10435 isl_ctx *ctx;
10436 isl_basic_map_list *list;
10437
10438 if (!map)
10439 return NULL;
10440 ctx = isl_map_get_ctx(map);
10441 list = isl_basic_map_list_alloc(ctx, map->n);
10442
10443 for (i = 0; i < map->n; ++i) {
10444 isl_basic_map *bmap;
10445
10446 bmap = isl_basic_map_copy(map->p[i]);
10447 list = isl_basic_map_list_add(list, bmap);
10448 }
10449
10450 return list;
10451}
10452
10453/* Return the intersection of the elements in the non-empty list "list".
10454 * All elements are assumed to live in the same space.
10455 */
10456__isl_give isl_basic_map *isl_basic_map_list_intersect(
10457 __isl_take isl_basic_map_list *list)
10458{
10459 int i;
10460 isl_size n;
10461 isl_basic_map *bmap;
10462
10463 n = isl_basic_map_list_n_basic_map(list);
10464 if (n < 0)
10465 goto error;
10466 if (n < 1)
10467 isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
10468 "expecting non-empty list", goto error);
10469
10470 bmap = isl_basic_map_list_get_basic_map(list, 0);
10471 for (i = 1; i < n; ++i) {
10472 isl_basic_map *bmap_i;
10473
10474 bmap_i = isl_basic_map_list_get_basic_map(list, i);
10475 bmap = isl_basic_map_intersect(bmap, bmap_i);
10476 }
10477
10478 isl_basic_map_list_free(list);
10479 return bmap;
10480error:
10481 isl_basic_map_list_free(list);
10482 return NULL;
10483}
10484
10485/* Return the intersection of the elements in the non-empty list "list".
10486 * All elements are assumed to live in the same space.
10487 */
10488__isl_give isl_basic_set *isl_basic_set_list_intersect(
10489 __isl_take isl_basic_set_list *list)
10490{
10491 return isl_basic_map_list_intersect(list);
10492}
10493
10494/* Return the union of the elements of "list".
10495 * The list is required to have at least one element.
10496 */
10497__isl_give isl_set *isl_basic_set_list_union(
10498 __isl_take isl_basic_set_list *list)
10499{
10500 int i;
10501 isl_size n;
10502 isl_space *space;
10503 isl_basic_set *bset;
10504 isl_set *set;
10505
10506 n = isl_basic_set_list_n_basic_set(list);
10507 if (n < 0)
10508 goto error;
10509 if (n < 1)
10510 isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
10511 "expecting non-empty list", goto error);
10512
10513 bset = isl_basic_set_list_get_basic_set(list, 0);
10514 space = isl_basic_set_get_space(bset);
10515 isl_basic_set_free(bset);
10516
10517 set = isl_set_alloc_space(space, n, 0);
10518 for (i = 0; i < n; ++i) {
10519 bset = isl_basic_set_list_get_basic_set(list, i);
10520 set = isl_set_add_basic_set(set, bset);
10521 }
10522
10523 isl_basic_set_list_free(list);
10524 return set;
10525error:
10526 isl_basic_set_list_free(list);
10527 return NULL;
10528}
10529
10530/* Return the union of the elements in the non-empty list "list".
10531 * All elements are assumed to live in the same space.
10532 */
10533__isl_give isl_set *isl_set_list_union(__isl_take isl_set_list *list)
10534{
10535 int i;
10536 isl_size n;
10537 isl_set *set;
10538
10539 n = isl_set_list_n_set(list);
10540 if (n < 0)
10541 goto error;
10542 if (n < 1)
10543 isl_die(isl_set_list_get_ctx(list), isl_error_invalid,
10544 "expecting non-empty list", goto error);
10545
10546 set = isl_set_list_get_set(list, 0);
10547 for (i = 1; i < n; ++i) {
10548 isl_set *set_i;
10549
10550 set_i = isl_set_list_get_set(list, i);
10551 set = isl_set_union(set, set_i);
10552 }
10553
10554 isl_set_list_free(list);
10555 return set;
10556error:
10557 isl_set_list_free(list);
10558 return NULL;
10559}
10560
10561__isl_give isl_basic_map *isl_basic_map_product(
10562 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10563{
10564 isl_space *space_result = NULL;
10565 struct isl_basic_map *bmap;
10566 unsigned in1, in2, out1, out2, nparam, total, pos;
10567 struct isl_dim_map *dim_map1, *dim_map2;
10568
10569 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10570 goto error;
10571 space_result = isl_space_product(isl_space_copy(bmap1->dim),
10572 isl_space_copy(bmap2->dim));
10573
10574 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10575 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10576 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10577 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10578 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10579
10580 total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
10581 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10582 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10583 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10584 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10585 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10586 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10587 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10588 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10589 isl_dim_map_div(dim_map1, bmap1, pos += out2);
10590 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10591
10592 bmap = isl_basic_map_alloc_space(space_result,
10593 bmap1->n_div + bmap2->n_div,
10594 bmap1->n_eq + bmap2->n_eq,
10595 bmap1->n_ineq + bmap2->n_ineq);
10596 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10597 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10598 bmap = isl_basic_map_simplify(bmap);
10599 return isl_basic_map_finalize(bmap);
10600error:
10601 isl_basic_map_free(bmap1);
10602 isl_basic_map_free(bmap2);
10603 return NULL;
10604}
10605
10606__isl_give isl_basic_map *isl_basic_map_flat_product(
10607 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10608{
10609 isl_basic_map *prod;
10610
10611 prod = isl_basic_map_product(bmap1, bmap2);
10612 prod = isl_basic_map_flatten(prod);
10613 return prod;
10614}
10615
10616__isl_give isl_basic_set *isl_basic_set_flat_product(
10617 __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
10618{
10619 return isl_basic_map_flat_range_product(bset1, bset2);
10620}
10621
10622__isl_give isl_basic_map *isl_basic_map_domain_product(
10623 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10624{
10625 isl_space *space1, *space2;
10626 isl_space *space_result = NULL;
10627 isl_basic_map *bmap;
10628 isl_size in1, in2, out, nparam;
10629 unsigned total, pos;
10630 struct isl_dim_map *dim_map1, *dim_map2;
10631
10632 in1 = isl_basic_map_dim(bmap1, isl_dim_in);
10633 in2 = isl_basic_map_dim(bmap2, isl_dim_in);
10634 out = isl_basic_map_dim(bmap1, isl_dim_out);
10635 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10636 if (in1 < 0 || in2 < 0 || out < 0 || nparam < 0)
10637 goto error;
10638
10639 space1 = isl_basic_map_get_space(bmap1);
10640 space2 = isl_basic_map_get_space(bmap2);
10641 space_result = isl_space_domain_product(space1, space2);
10642
10643 total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
10644 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10645 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10646 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10647 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10648 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10649 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
10650 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
10651 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
10652 isl_dim_map_div(dim_map1, bmap1, pos += out);
10653 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10654
10655 bmap = isl_basic_map_alloc_space(space_result,
10656 bmap1->n_div + bmap2->n_div,
10657 bmap1->n_eq + bmap2->n_eq,
10658 bmap1->n_ineq + bmap2->n_ineq);
10659 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10660 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10661 bmap = isl_basic_map_simplify(bmap);
10662 return isl_basic_map_finalize(bmap);
10663error:
10664 isl_basic_map_free(bmap1);
10665 isl_basic_map_free(bmap2);
10666 return NULL;
10667}
10668
10669__isl_give isl_basic_map *isl_basic_map_range_product(
10670 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10671{
10672 isl_bool rational;
10673 isl_space *space_result = NULL;
10674 isl_basic_map *bmap;
10675 isl_size in, out1, out2, nparam;
10676 unsigned total, pos;
10677 struct isl_dim_map *dim_map1, *dim_map2;
10678
10679 rational = isl_basic_map_is_rational(bmap1);
10680 if (rational >= 0 && rational)
10681 rational = isl_basic_map_is_rational(bmap2);
10682 in = isl_basic_map_dim(bmap1, isl_dim_in);
10683 out1 = isl_basic_map_dim(bmap1, isl_dim_out);
10684 out2 = isl_basic_map_dim(bmap2, isl_dim_out);
10685 nparam = isl_basic_map_dim(bmap1, isl_dim_param);
10686 if (in < 0 || out1 < 0 || out2 < 0 || nparam < 0 || rational < 0)
10687 goto error;
10688
10689 if (isl_basic_map_check_equal_params(bmap1, bmap2) < 0)
10690 goto error;
10691
10692 space_result = isl_space_range_product(isl_space_copy(bmap1->dim),
10693 isl_space_copy(bmap2->dim));
10694
10695 total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
10696 dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
10697 dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
10698 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
10699 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
10700 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
10701 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
10702 isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
10703 isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
10704 isl_dim_map_div(dim_map1, bmap1, pos += out2);
10705 isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
10706
10707 bmap = isl_basic_map_alloc_space(space_result,
10708 bmap1->n_div + bmap2->n_div,
10709 bmap1->n_eq + bmap2->n_eq,
10710 bmap1->n_ineq + bmap2->n_ineq);
10711 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
10712 bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
10713 if (rational)
10714 bmap = isl_basic_map_set_rational(bmap);
10715 bmap = isl_basic_map_simplify(bmap);
10716 return isl_basic_map_finalize(bmap);
10717error:
10718 isl_basic_map_free(bmap1);
10719 isl_basic_map_free(bmap2);
10720 return NULL;
10721}
10722
10723__isl_give isl_basic_map *isl_basic_map_flat_range_product(
10724 __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
10725{
10726 isl_basic_map *prod;
10727
10728 prod = isl_basic_map_range_product(bmap1, bmap2);
10729 prod = isl_basic_map_flatten_range(prod);
10730 return prod;
10731}
10732
10733/* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
10734 * and collect the results.
10735 * The result live in the space obtained by calling "space_product"
10736 * on the spaces of "map1" and "map2".
10737 * If "remove_duplicates" is set then the result may contain duplicates
10738 * (even if the inputs do not) and so we try and remove the obvious
10739 * duplicates.
10740 */
10741static __isl_give isl_map *map_product(__isl_take isl_map *map1,
10742 __isl_take isl_map *map2,
10743 __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
10744 __isl_take isl_space *right),
10745 __isl_give isl_basic_map *(*basic_map_product)(
10746 __isl_take isl_basic_map *left,
10747 __isl_take isl_basic_map *right),
10748 int remove_duplicates)
10749{
10750 unsigned flags = 0;
10751 struct isl_map *result;
10752 int i, j;
10753 isl_bool m;
10754
10755 m = isl_map_has_equal_params(map1, map2);
10756 if (m < 0)
10757 goto error;
10758 if (!m)
10759 isl_die(isl_map_get_ctx(map1), isl_error_invalid,
10760 "parameters don't match", goto error);
10761
10762 if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
10763 ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
10764 ISL_FL_SET(flags, ISL_MAP_DISJOINT);
10765
10766 result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
10767 isl_space_copy(map2->dim)),
10768 map1->n * map2->n, flags);
10769 if (!result)
10770 goto error;
10771 for (i = 0; i < map1->n; ++i)
10772 for (j = 0; j < map2->n; ++j) {
10773 struct isl_basic_map *part;
10774 part = basic_map_product(isl_basic_map_copy(map1->p[i]),
10775 isl_basic_map_copy(map2->p[j]));
10776 if (isl_basic_map_is_empty(part))
10777 isl_basic_map_free(part);
10778 else
10779 result = isl_map_add_basic_map(result, part);
10780 if (!result)
10781 goto error;
10782 }
10783 if (remove_duplicates)
10784 result = isl_map_remove_obvious_duplicates(result);
10785 isl_map_free(map1);
10786 isl_map_free(map2);
10787 return result;
10788error:
10789 isl_map_free(map1);
10790 isl_map_free(map2);
10791 return NULL;
10792}
10793
10794/* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
10795 */
10796__isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
10797 __isl_take isl_map *map2)
10798{
10799 isl_map_align_params_bin(&map1, &map2);
10800 return map_product(map1, map2, &isl_space_product,
10801 &isl_basic_map_product, 0);
10802}
10803
10804/* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
10805 */
10806__isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
10807 __isl_take isl_map *map2)
10808{
10809 isl_map *prod;
10810
10811 prod = isl_map_product(map1, map2);
10812 prod = isl_map_flatten(prod);
10813 return prod;
10814}
10815
10816/* Given two set A and B, construct its Cartesian product A x B.
10817 */
10818__isl_give isl_set *isl_set_product(__isl_take isl_set *set1,
10819 __isl_take isl_set *set2)
10820{
10821 return isl_map_range_product(set1, set2);
10822}
10823
10824__isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
10825 __isl_take isl_set *set2)
10826{
10827 return isl_map_flat_range_product(set1, set2);
10828}
10829
10830/* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
10831 */
10832__isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
10833 __isl_take isl_map *map2)
10834{
10835 isl_map_align_params_bin(&map1, &map2);
10836 return map_product(map1, map2, &isl_space_domain_product,
10837 &isl_basic_map_domain_product, 1);
10838}
10839
10840/* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
10841 */
10842__isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
10843 __isl_take isl_map *map2)
10844{
10845 isl_map_align_params_bin(&map1, &map2);
10846 return map_product(map1, map2, &isl_space_range_product,
10847 &isl_basic_map_range_product, 1);
10848}
10849
10850/* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
10851 */
10852__isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
10853{
10854 isl_space *space;
10855 isl_size total1, keep1, total2, keep2;
10856
10857 total1 = isl_map_dim(map, isl_dim_in);
10858 total2 = isl_map_dim(map, isl_dim_out);
10859 if (total1 < 0 || total2 < 0)
10860 return isl_map_free(map);
10861 if (!isl_space_domain_is_wrapping(map->dim) ||
10862 !isl_space_range_is_wrapping(map->dim))
10863 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10864 "not a product", return isl_map_free(map));
10865
10866 space = isl_map_get_space(map);
10867 space = isl_space_factor_domain(space);
10868 keep1 = isl_space_dim(space, isl_dim_in);
10869 keep2 = isl_space_dim(space, isl_dim_out);
10870 if (keep1 < 0 || keep2 < 0)
10871 map = isl_map_free(map);
10872 map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
10873 map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
10874 map = isl_map_reset_space(map, space);
10875
10876 return map;
10877}
10878
10879/* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
10880 */
10881__isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
10882{
10883 isl_space *space;
10884 isl_size total1, keep1, total2, keep2;
10885
10886 total1 = isl_map_dim(map, isl_dim_in);
10887 total2 = isl_map_dim(map, isl_dim_out);
10888 if (total1 < 0 || total2 < 0)
10889 return isl_map_free(map);
10890 if (!isl_space_domain_is_wrapping(map->dim) ||
10891 !isl_space_range_is_wrapping(map->dim))
10892 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10893 "not a product", return isl_map_free(map));
10894
10895 space = isl_map_get_space(map);
10896 space = isl_space_factor_range(space);
10897 keep1 = isl_space_dim(space, isl_dim_in);
10898 keep2 = isl_space_dim(space, isl_dim_out);
10899 if (keep1 < 0 || keep2 < 0)
10900 map = isl_map_free(map);
10901 map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
10902 map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
10903 map = isl_map_reset_space(map, space);
10904
10905 return map;
10906}
10907
10908/* Given a map of the form [A -> B] -> C, return the map A -> C.
10909 */
10910__isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
10911{
10912 isl_space *space;
10913 isl_size total, keep;
10914
10915 total = isl_map_dim(map, isl_dim_in);
10916 if (total < 0)
10917 return isl_map_free(map);
10918 if (!isl_space_domain_is_wrapping(map->dim))
10919 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10920 "domain is not a product", return isl_map_free(map));
10921
10922 space = isl_map_get_space(map);
10923 space = isl_space_domain_factor_domain(space);
10924 keep = isl_space_dim(space, isl_dim_in);
10925 if (keep < 0)
10926 map = isl_map_free(map);
10927 map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
10928 map = isl_map_reset_space(map, space);
10929
10930 return map;
10931}
10932
10933/* Given a map of the form [A -> B] -> C, return the map B -> C.
10934 */
10935__isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
10936{
10937 isl_space *space;
10938 isl_size total, keep;
10939
10940 total = isl_map_dim(map, isl_dim_in);
10941 if (total < 0)
10942 return isl_map_free(map);
10943 if (!isl_space_domain_is_wrapping(map->dim))
10944 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10945 "domain is not a product", return isl_map_free(map));
10946
10947 space = isl_map_get_space(map);
10948 space = isl_space_domain_factor_range(space);
10949 keep = isl_space_dim(space, isl_dim_in);
10950 if (keep < 0)
10951 map = isl_map_free(map);
10952 map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
10953 map = isl_map_reset_space(map, space);
10954
10955 return map;
10956}
10957
10958/* Given a map A -> [B -> C], extract the map A -> B.
10959 */
10960__isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
10961{
10962 isl_space *space;
10963 isl_size total, keep;
10964
10965 total = isl_map_dim(map, isl_dim_out);
10966 if (total < 0)
10967 return isl_map_free(map);
10968 if (!isl_space_range_is_wrapping(map->dim))
10969 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10970 "range is not a product", return isl_map_free(map));
10971
10972 space = isl_map_get_space(map);
10973 space = isl_space_range_factor_domain(space);
10974 keep = isl_space_dim(space, isl_dim_out);
10975 if (keep < 0)
10976 map = isl_map_free(map);
10977 map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
10978 map = isl_map_reset_space(map, space);
10979
10980 return map;
10981}
10982
10983/* Given a map A -> [B -> C], extract the map A -> C.
10984 */
10985__isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
10986{
10987 isl_space *space;
10988 isl_size total, keep;
10989
10990 total = isl_map_dim(map, isl_dim_out);
10991 if (total < 0)
10992 return isl_map_free(map);
10993 if (!isl_space_range_is_wrapping(map->dim))
10994 isl_die(isl_map_get_ctx(map), isl_error_invalid,
10995 "range is not a product", return isl_map_free(map));
10996
10997 space = isl_map_get_space(map);
10998 space = isl_space_range_factor_range(space);
10999 keep = isl_space_dim(space, isl_dim_out);
11000 if (keep < 0)
11001 map = isl_map_free(map);
11002 map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
11003 map = isl_map_reset_space(map, space);
11004
11005 return map;
11006}
11007
11008/* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
11009 */
11010__isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
11011 __isl_take isl_map *map2)
11012{
11013 isl_map *prod;
11014
11015 prod = isl_map_domain_product(map1, map2);
11016 prod = isl_map_flatten_domain(prod);
11017 return prod;
11018}
11019
11020/* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
11021 */
11022__isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
11023 __isl_take isl_map *map2)
11024{
11025 isl_map *prod;
11026
11027 prod = isl_map_range_product(map1, map2);
11028 prod = isl_map_flatten_range(prod);
11029 return prod;
11030}
11031
11032uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
11033{
11034 int i;
11035 uint32_t hash = isl_hash_init();
11036 isl_size total;
11037
11038 if (!bmap)
11039 return 0;
11040 bmap = isl_basic_map_copy(bmap);
11041 bmap = isl_basic_map_normalize(bmap);
11042 total = isl_basic_map_dim(bmap, isl_dim_all);
11043 if (total < 0)
11044 return 0;
11045 isl_hash_byte(hash, bmap->n_eq & 0xFF);
11046 for (i = 0; i < bmap->n_eq; ++i) {
11047 uint32_t c_hash;
11048 c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
11049 isl_hash_hash(hash, c_hash);
11050 }
11051 isl_hash_byte(hash, bmap->n_ineq & 0xFF);
11052 for (i = 0; i < bmap->n_ineq; ++i) {
11053 uint32_t c_hash;
11054 c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
11055 isl_hash_hash(hash, c_hash);
11056 }
11057 isl_hash_byte(hash, bmap->n_div & 0xFF);
11058 for (i = 0; i < bmap->n_div; ++i) {
11059 uint32_t c_hash;
11060 if (isl_int_is_zero(bmap->div[i][0]))
11061 continue;
11062 isl_hash_byte(hash, i & 0xFF);
11063 c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
11064 isl_hash_hash(hash, c_hash);
11065 }
11066 isl_basic_map_free(bmap);
11067 return hash;
11068}
11069
11070uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
11071{
11072 return isl_basic_map_get_hash(bset_to_bmap(bset));
11073}
11074
11075uint32_t isl_map_get_hash(__isl_keep isl_map *map)
11076{
11077 int i;
11078 uint32_t hash;
11079
11080 if (!map)
11081 return 0;
11082 map = isl_map_copy(map);
11083 map = isl_map_normalize(map);
11084 if (!map)
11085 return 0;
11086
11087 hash = isl_hash_init();
11088 for (i = 0; i < map->n; ++i) {
11089 uint32_t bmap_hash;
11090 bmap_hash = isl_basic_map_get_hash(map->p[i]);
11091 isl_hash_hash(hash, bmap_hash);
11092 }
11093
11094 isl_map_free(map);
11095
11096 return hash;
11097}
11098
11099uint32_t isl_set_get_hash(__isl_keep isl_set *set)
11100{
11101 return isl_map_get_hash(set_to_map(set));
11102}
11103
11104/* Return the number of basic maps in the (current) representation of "map".
11105 */
11106isl_size isl_map_n_basic_map(__isl_keep isl_map *map)
11107{
11108 return map ? map->n : isl_size_error;
11109}
11110
11111isl_size isl_set_n_basic_set(__isl_keep isl_set *set)
11112{
11113 return set ? set->n : isl_size_error;
11114}
11115
11116isl_stat isl_map_foreach_basic_map(__isl_keep isl_map *map,
11117 isl_stat (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
11118{
11119 int i;
11120
11121 if (!map)
11122 return isl_stat_error;
11123
11124 for (i = 0; i < map->n; ++i)
11125 if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
11126 return isl_stat_error;
11127
11128 return isl_stat_ok;
11129}
11130
11131isl_stat isl_set_foreach_basic_set(__isl_keep isl_set *set,
11132 isl_stat (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
11133{
11134 int i;
11135
11136 if (!set)
11137 return isl_stat_error;
11138
11139 for (i = 0; i < set->n; ++i)
11140 if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
11141 return isl_stat_error;
11142
11143 return isl_stat_ok;
11144}
11145
11146/* Does "test" succeed on every basic set in "set"?
11147 */
11148isl_bool isl_set_every_basic_set(__isl_keep isl_set *set,
11149 isl_bool (*test)(__isl_keep isl_basic_set *bset, void *user),
11150 void *user)
11151{
11152 int i;
11153
11154 if (!set)
11155 return isl_bool_error;
11156
11157 for (i = 0; i < set->n; ++i) {
11158 isl_bool r;
11159
11160 r = test(set->p[i], user);
11161 if (r < 0 || !r)
11162 return r;
11163 }
11164
11165 return isl_bool_true;
11166}
11167
11168/* Return a list of basic sets, the union of which is equal to "set".
11169 */
11170__isl_give isl_basic_set_list *isl_set_get_basic_set_list(
11171 __isl_keep isl_set *set)
11172{
11173 int i;
11174 isl_basic_set_list *list;
11175
11176 if (!set)
11177 return NULL;
11178
11179 list = isl_basic_set_list_alloc(isl_set_get_ctx(set), set->n);
11180 for (i = 0; i < set->n; ++i) {
11181 isl_basic_set *bset;
11182
11183 bset = isl_basic_set_copy(set->p[i]);
11184 list = isl_basic_set_list_add(list, bset);
11185 }
11186
11187 return list;
11188}
11189
11190__isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
11191{
11192 isl_space *space;
11193
11194 if (!bset)
11195 return NULL;
11196
11197 bset = isl_basic_set_cow(bset);
11198 if (!bset)
11199 return NULL;
11200
11201 space = isl_basic_set_get_space(bset);
11202 space = isl_space_lift(space, bset->n_div);
11203 if (!space)
11204 goto error;
11205 isl_space_free(bset->dim);
11206 bset->dim = space;
11207 bset->extra -= bset->n_div;
11208 bset->n_div = 0;
11209
11210 bset = isl_basic_set_finalize(bset);
11211
11212 return bset;
11213error:
11214 isl_basic_set_free(bset);
11215 return NULL;
11216}
11217
11218__isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
11219{
11220 int i;
11221 isl_space *space;
11222 unsigned n_div;
11223
11224 set = set_from_map(isl_map_align_divs_internal(set_to_map(set)));
11225
11226 if (!set)
11227 return NULL;
11228
11229 set = isl_set_cow(set);
11230 if (!set)
11231 return NULL;
11232
11233 n_div = set->p[0]->n_div;
11234 space = isl_set_get_space(set);
11235 space = isl_space_lift(space, n_div);
11236 if (!space)
11237 goto error;
11238 isl_space_free(set->dim);
11239 set->dim = space;
11240
11241 for (i = 0; i < set->n; ++i) {
11242 set->p[i] = isl_basic_set_lift(set->p[i]);
11243 if (!set->p[i])
11244 goto error;
11245 }
11246
11247 return set;
11248error:
11249 isl_set_free(set);
11250 return NULL;
11251}
11252
11253int isl_basic_set_size(__isl_keep isl_basic_set *bset)
11254{
11255 isl_size dim;
11256 int size = 0;
11257
11258 dim = isl_basic_set_dim(bset, isl_dim_all);
11259 if (dim < 0)
11260 return -1;
11261 size += bset->n_eq * (1 + dim);
11262 size += bset->n_ineq * (1 + dim);
11263 size += bset->n_div * (2 + dim);
11264
11265 return size;
11266}
11267
11268int isl_set_size(__isl_keep isl_set *set)
11269{
11270 int i;
11271 int size = 0;
11272
11273 if (!set)
11274 return -1;
11275
11276 for (i = 0; i < set->n; ++i)
11277 size += isl_basic_set_size(set->p[i]);
11278
11279 return size;
11280}
11281
11282/* Check if there is any lower bound (if lower == 0) and/or upper
11283 * bound (if upper == 0) on the specified dim.
11284 */
11285static isl_bool basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11286 enum isl_dim_type type, unsigned pos, int lower, int upper)
11287{
11288 int i;
11289
11290 if (isl_basic_map_check_range(bmap, type, pos, 1) < 0)
11291 return isl_bool_error;
11292
11293 pos += isl_basic_map_offset(bmap, type);
11294
11295 for (i = 0; i < bmap->n_div; ++i) {
11296 if (isl_int_is_zero(bmap->div[i][0]))
11297 continue;
11298 if (!isl_int_is_zero(bmap->div[i][1 + pos]))
11299 return isl_bool_true;
11300 }
11301
11302 for (i = 0; i < bmap->n_eq; ++i)
11303 if (!isl_int_is_zero(bmap->eq[i][pos]))
11304 return isl_bool_true;
11305
11306 for (i = 0; i < bmap->n_ineq; ++i) {
11307 int sgn = isl_int_sgn(bmap->ineq[i][pos]);
11308 if (sgn > 0)
11309 lower = 1;
11310 if (sgn < 0)
11311 upper = 1;
11312 }
11313
11314 return lower && upper;
11315}
11316
11317isl_bool isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
11318 enum isl_dim_type type, unsigned pos)
11319{
11320 return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
11321}
11322
11323isl_bool isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
11324 enum isl_dim_type type, unsigned pos)
11325{
11326 return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
11327}
11328
11329isl_bool isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
11330 enum isl_dim_type type, unsigned pos)
11331{
11332 return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
11333}
11334
11335isl_bool isl_map_dim_is_bounded(__isl_keep isl_map *map,
11336 enum isl_dim_type type, unsigned pos)
11337{
11338 int i;
11339
11340 if (!map)
11341 return isl_bool_error;
11342
11343 for (i = 0; i < map->n; ++i) {
11344 isl_bool bounded;
11345 bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
11346 if (bounded < 0 || !bounded)
11347 return bounded;
11348 }
11349
11350 return isl_bool_true;
11351}
11352
11353/* Return true if the specified dim is involved in both an upper bound
11354 * and a lower bound.
11355 */
11356isl_bool isl_set_dim_is_bounded(__isl_keep isl_set *set,
11357 enum isl_dim_type type, unsigned pos)
11358{
11359 return isl_map_dim_is_bounded(set_to_map(set), type, pos);
11360}
11361
11362/* Does "map" have a bound (according to "fn") for any of its basic maps?
11363 */
11364static isl_bool has_any_bound(__isl_keep isl_map *map,
11365 enum isl_dim_type type, unsigned pos,
11366 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11367 enum isl_dim_type type, unsigned pos))
11368{
11369 int i;
11370
11371 if (!map)
11372 return isl_bool_error;
11373
11374 for (i = 0; i < map->n; ++i) {
11375 isl_bool bounded;
11376 bounded = fn(map->p[i], type, pos);
11377 if (bounded < 0 || bounded)
11378 return bounded;
11379 }
11380
11381 return isl_bool_false;
11382}
11383
11384/* Return 1 if the specified dim is involved in any lower bound.
11385 */
11386isl_bool isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
11387 enum isl_dim_type type, unsigned pos)
11388{
11389 return has_any_bound(set, type, pos,
11390 &isl_basic_map_dim_has_lower_bound);
11391}
11392
11393/* Return 1 if the specified dim is involved in any upper bound.
11394 */
11395isl_bool isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
11396 enum isl_dim_type type, unsigned pos)
11397{
11398 return has_any_bound(set, type, pos,
11399 &isl_basic_map_dim_has_upper_bound);
11400}
11401
11402/* Does "map" have a bound (according to "fn") for all of its basic maps?
11403 */
11404static isl_bool has_bound(__isl_keep isl_map *map,
11405 enum isl_dim_type type, unsigned pos,
11406 isl_bool (*fn)(__isl_keep isl_basic_map *bmap,
11407 enum isl_dim_type type, unsigned pos))
11408{
11409 int i;
11410
11411 if (!map)
11412 return isl_bool_error;
11413
11414 for (i = 0; i < map->n; ++i) {
11415 isl_bool bounded;
11416 bounded = fn(map->p[i], type, pos);
11417 if (bounded < 0 || !bounded)
11418 return bounded;
11419 }
11420
11421 return isl_bool_true;
11422}
11423
11424/* Return 1 if the specified dim has a lower bound (in each of its basic sets).
11425 */
11426isl_bool isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
11427 enum isl_dim_type type, unsigned pos)
11428{
11429 return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
11430}
11431
11432/* Return 1 if the specified dim has an upper bound (in each of its basic sets).
11433 */
11434isl_bool isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
11435 enum isl_dim_type type, unsigned pos)
11436{
11437 return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
11438}
11439
11440/* For each of the "n" variables starting at "first", determine
11441 * the sign of the variable and put the results in the first "n"
11442 * elements of the array "signs".
11443 * Sign
11444 * 1 means that the variable is non-negative
11445 * -1 means that the variable is non-positive
11446 * 0 means the variable attains both positive and negative values.
11447 */
11448isl_stat isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
11449 unsigned first, unsigned n, int *signs)
11450{
11451 isl_vec *bound = NULL;
11452 struct isl_tab *tab = NULL;
11453 struct isl_tab_undo *snap;
11454 int i;
11455 isl_size total;
11456
11457 total = isl_basic_set_dim(bset, isl_dim_all);
11458 if (total < 0 || !signs)
11459 return isl_stat_error;
11460
11461 bound = isl_vec_alloc(bset->ctx, 1 + total);
11462 tab = isl_tab_from_basic_set(bset, 0);
11463 if (!bound || !tab)
11464 goto error;
11465
11466 isl_seq_clr(bound->el, bound->size);
11467 isl_int_set_si(bound->el[0], -1);
11468
11469 snap = isl_tab_snap(tab);
11470 for (i = 0; i < n; ++i) {
11471 int empty;
11472
11473 isl_int_set_si(bound->el[1 + first + i], -1);
11474 if (isl_tab_add_ineq(tab, bound->el) < 0)
11475 goto error;
11476 empty = tab->empty;
11477 isl_int_set_si(bound->el[1 + first + i], 0);
11478 if (isl_tab_rollback(tab, snap) < 0)
11479 goto error;
11480
11481 if (empty) {
11482 signs[i] = 1;
11483 continue;
11484 }
11485
11486 isl_int_set_si(bound->el[1 + first + i], 1);
11487 if (isl_tab_add_ineq(tab, bound->el) < 0)
11488 goto error;
11489 empty = tab->empty;
11490 isl_int_set_si(bound->el[1 + first + i], 0);
11491 if (isl_tab_rollback(tab, snap) < 0)
11492 goto error;
11493
11494 signs[i] = empty ? -1 : 0;
11495 }
11496
11497 isl_tab_free(tab);
11498 isl_vec_free(bound);
11499 return isl_stat_ok;
11500error:
11501 isl_tab_free(tab);
11502 isl_vec_free(bound);
11503 return isl_stat_error;
11504}
11505
11506isl_stat isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
11507 enum isl_dim_type type, unsigned first, unsigned n, int *signs)
11508{
11509 if (!bset || !signs)
11510 return isl_stat_error;
11511 if (isl_basic_set_check_range(bset, type, first, n) < 0)
11512 return isl_stat_error;
11513
11514 first += pos(bset->dim, type) - 1;
11515 return isl_basic_set_vars_get_sign(bset, first, n, signs);
11516}
11517
11518/* Is it possible for the integer division "div" to depend (possibly
11519 * indirectly) on any output dimensions?
11520 *
11521 * If the div is undefined, then we conservatively assume that it
11522 * may depend on them.
11523 * Otherwise, we check if it actually depends on them or on any integer
11524 * divisions that may depend on them.
11525 */
11526static isl_bool div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
11527{
11528 int i;
11529 isl_size n_out, n_div;
11530 unsigned o_out, o_div;
11531
11532 if (isl_int_is_zero(bmap->div[div][0]))
11533 return isl_bool_true;
11534
11535 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11536 if (n_out < 0)
11537 return isl_bool_error;
11538 o_out = isl_basic_map_offset(bmap, isl_dim_out);
11539
11540 if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
11541 return isl_bool_true;
11542
11543 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11544 if (n_div < 0)
11545 return isl_bool_error;
11546 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11547
11548 for (i = 0; i < n_div; ++i) {
11549 isl_bool may_involve;
11550
11551 if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
11552 continue;
11553 may_involve = div_may_involve_output(bmap, i);
11554 if (may_involve < 0 || may_involve)
11555 return may_involve;
11556 }
11557
11558 return isl_bool_false;
11559}
11560
11561/* Return the first integer division of "bmap" in the range
11562 * [first, first + n[ that may depend on any output dimensions and
11563 * that has a non-zero coefficient in "c" (where the first coefficient
11564 * in "c" corresponds to integer division "first").
11565 */
11566static int first_div_may_involve_output(__isl_keep isl_basic_map *bmap,
11567 isl_int *c, int first, int n)
11568{
11569 int k;
11570
11571 if (!bmap)
11572 return -1;
11573
11574 for (k = first; k < first + n; ++k) {
11575 isl_bool may_involve;
11576
11577 if (isl_int_is_zero(c[k]))
11578 continue;
11579 may_involve = div_may_involve_output(bmap, k);
11580 if (may_involve < 0)
11581 return -1;
11582 if (may_involve)
11583 return k;
11584 }
11585
11586 return first + n;
11587}
11588
11589/* Look for a pair of inequality constraints in "bmap" of the form
11590 *
11591 * -l + i >= 0 or i >= l
11592 * and
11593 * n + l - i >= 0 or i <= l + n
11594 *
11595 * with n < "m" and i the output dimension at position "pos".
11596 * (Note that n >= 0 as otherwise the two constraints would conflict.)
11597 * Furthermore, "l" is only allowed to involve parameters, input dimensions
11598 * and earlier output dimensions, as well as integer divisions that do
11599 * not involve any of the output dimensions.
11600 *
11601 * Return the index of the first inequality constraint or bmap->n_ineq
11602 * if no such pair can be found.
11603 */
11604static int find_modulo_constraint_pair(__isl_keep isl_basic_map *bmap,
11605 int pos, isl_int m)
11606{
11607 int i, j;
11608 isl_ctx *ctx;
11609 isl_size total;
11610 isl_size n_div, n_out;
11611 unsigned o_div, o_out;
11612 int less;
11613
11614 total = isl_basic_map_dim(bmap, isl_dim_all);
11615 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11616 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11617 if (total < 0 || n_out < 0 || n_div < 0)
11618 return -1;
11619
11620 ctx = isl_basic_map_get_ctx(bmap);
11621 o_out = isl_basic_map_offset(bmap, isl_dim_out);
11622 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11623 for (i = 0; i < bmap->n_ineq; ++i) {
11624 if (!isl_int_abs_eq(bmap->ineq[i][o_out + pos], ctx->one))
11625 continue;
11626 if (isl_seq_first_non_zero(bmap->ineq[i] + o_out + pos + 1,
11627 n_out - (pos + 1)) != -1)
11628 continue;
11629 if (first_div_may_involve_output(bmap, bmap->ineq[i] + o_div,
11630 0, n_div) < n_div)
11631 continue;
11632 for (j = i + 1; j < bmap->n_ineq; ++j) {
11633 if (!isl_int_abs_eq(bmap->ineq[j][o_out + pos],
11634 ctx->one))
11635 continue;
11636 if (!isl_seq_is_neg(bmap->ineq[i] + 1,
11637 bmap->ineq[j] + 1, total))
11638 continue;
11639 break;
11640 }
11641 if (j >= bmap->n_ineq)
11642 continue;
11643 isl_int_add(bmap->ineq[i][0],
11644 bmap->ineq[i][0], bmap->ineq[j][0]);
11645 less = isl_int_abs_lt(bmap->ineq[i][0], m);
11646 isl_int_sub(bmap->ineq[i][0],
11647 bmap->ineq[i][0], bmap->ineq[j][0]);
11648 if (!less)
11649 continue;
11650 if (isl_int_is_one(bmap->ineq[i][o_out + pos]))
11651 return i;
11652 else
11653 return j;
11654 }
11655
11656 return bmap->n_ineq;
11657}
11658
11659/* Return the index of the equality of "bmap" that defines
11660 * the output dimension "pos" in terms of earlier dimensions.
11661 * The equality may also involve integer divisions, as long
11662 * as those integer divisions are defined in terms of
11663 * parameters or input dimensions.
11664 * In this case, *div is set to the number of integer divisions and
11665 * *ineq is set to the number of inequality constraints (provided
11666 * div and ineq are not NULL).
11667 *
11668 * The equality may also involve a single integer division involving
11669 * the output dimensions (typically only output dimension "pos") as
11670 * long as the coefficient of output dimension "pos" is 1 or -1 and
11671 * there is a pair of constraints i >= l and i <= l + n, with i referring
11672 * to output dimension "pos", l an expression involving only earlier
11673 * dimensions and n smaller than the coefficient of the integer division
11674 * in the equality. In this case, the output dimension can be defined
11675 * in terms of a modulo expression that does not involve the integer division.
11676 * *div is then set to this single integer division and
11677 * *ineq is set to the index of constraint i >= l.
11678 *
11679 * Return bmap->n_eq if there is no such equality.
11680 * Return -1 on error.
11681 */
11682int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
11683 int pos, int *div, int *ineq)
11684{
11685 int j, k, l;
11686 isl_size n_div, n_out;
11687 unsigned o_div, o_out;
11688
11689 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11690 n_div = isl_basic_map_dim(bmap, isl_dim_div);
11691 if (n_out < 0 || n_div < 0)
11692 return -1;
11693
11694 o_out = isl_basic_map_offset(bmap, isl_dim_out);
11695 o_div = isl_basic_map_offset(bmap, isl_dim_div);
11696
11697 if (ineq)
11698 *ineq = bmap->n_ineq;
11699 if (div)
11700 *div = n_div;
11701 for (j = 0; j < bmap->n_eq; ++j) {
11702 if (isl_int_is_zero(bmap->eq[j][o_out + pos]))
11703 continue;
11704 if (isl_seq_first_non_zero(bmap->eq[j] + o_out + pos + 1,
11705 n_out - (pos + 1)) != -1)
11706 continue;
11707 k = first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11708 0, n_div);
11709 if (k >= n_div)
11710 return j;
11711 if (!isl_int_is_one(bmap->eq[j][o_out + pos]) &&
11712 !isl_int_is_negone(bmap->eq[j][o_out + pos]))
11713 continue;
11714 if (first_div_may_involve_output(bmap, bmap->eq[j] + o_div,
11715 k + 1, n_div - (k+1)) < n_div)
11716 continue;
11717 l = find_modulo_constraint_pair(bmap, pos,
11718 bmap->eq[j][o_div + k]);
11719 if (l < 0)
11720 return -1;
11721 if (l >= bmap->n_ineq)
11722 continue;
11723 if (div)
11724 *div = k;
11725 if (ineq)
11726 *ineq = l;
11727 return j;
11728 }
11729
11730 return bmap->n_eq;
11731}
11732
11733/* Check if the given basic map is obviously single-valued.
11734 * In particular, for each output dimension, check that there is
11735 * an equality that defines the output dimension in terms of
11736 * earlier dimensions.
11737 */
11738isl_bool isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
11739{
11740 int i;
11741 isl_size n_out;
11742
11743 n_out = isl_basic_map_dim(bmap, isl_dim_out);
11744 if (n_out < 0)
11745 return isl_bool_error;
11746
11747 for (i = 0; i < n_out; ++i) {
11748 int eq;
11749
11750 eq = isl_basic_map_output_defining_equality(bmap, i,
11751 NULL, NULL);
11752 if (eq < 0)
11753 return isl_bool_error;
11754 if (eq >= bmap->n_eq)
11755 return isl_bool_false;
11756 }
11757
11758 return isl_bool_true;
11759}
11760
11761/* Check if the given basic map is single-valued.
11762 * We simply compute
11763 *
11764 * M \circ M^-1
11765 *
11766 * and check if the result is a subset of the identity mapping.
11767 */
11768isl_bool isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
11769{
11770 isl_space *space;
11771 isl_basic_map *test;
11772 isl_basic_map *id;
11773 isl_bool sv;
11774
11775 sv = isl_basic_map_plain_is_single_valued(bmap);
11776 if (sv < 0 || sv)
11777 return sv;
11778
11779 test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
11780 test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
11781
11782 space = isl_basic_map_get_space(bmap);
11783 space = isl_space_map_from_set(isl_space_range(space));
11784 id = isl_basic_map_identity(space);
11785
11786 sv = isl_basic_map_is_subset(test, id);
11787
11788 isl_basic_map_free(test);
11789 isl_basic_map_free(id);
11790
11791 return sv;
11792}
11793
11794/* Check if the given map is obviously single-valued.
11795 */
11796isl_bool isl_map_plain_is_single_valued(__isl_keep isl_map *map)
11797{
11798 if (!map)
11799 return isl_bool_error;
11800 if (map->n == 0)
11801 return isl_bool_true;
11802 if (map->n >= 2)
11803 return isl_bool_false;
11804
11805 return isl_basic_map_plain_is_single_valued(map->p[0]);
11806}
11807
11808/* Check if the given map is single-valued.
11809 * We simply compute
11810 *
11811 * M \circ M^-1
11812 *
11813 * and check if the result is a subset of the identity mapping.
11814 */
11815isl_bool isl_map_is_single_valued(__isl_keep isl_map *map)
11816{
11817 isl_space *space;
11818 isl_map *test;
11819 isl_map *id;
11820 isl_bool sv;
11821
11822 sv = isl_map_plain_is_single_valued(map);
11823 if (sv < 0 || sv)
11824 return sv;
11825
11826 test = isl_map_reverse(isl_map_copy(map));
11827 test = isl_map_apply_range(test, isl_map_copy(map));
11828
11829 space = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
11830 id = isl_map_identity(space);
11831
11832 sv = isl_map_is_subset(test, id);
11833
11834 isl_map_free(test);
11835 isl_map_free(id);
11836
11837 return sv;
11838}
11839
11840isl_bool isl_map_is_injective(__isl_keep isl_map *map)
11841{
11842 isl_bool in;
11843
11844 map = isl_map_copy(map);
11845 map = isl_map_reverse(map);
11846 in = isl_map_is_single_valued(map);
11847 isl_map_free(map);
11848
11849 return in;
11850}
11851
11852/* Check if the given map is obviously injective.
11853 */
11854isl_bool isl_map_plain_is_injective(__isl_keep isl_map *map)
11855{
11856 isl_bool in;
11857
11858 map = isl_map_copy(map);
11859 map = isl_map_reverse(map);
11860 in = isl_map_plain_is_single_valued(map);
11861 isl_map_free(map);
11862
11863 return in;
11864}
11865
11866isl_bool isl_map_is_bijective(__isl_keep isl_map *map)
11867{
11868 isl_bool sv;
11869
11870 sv = isl_map_is_single_valued(map);
11871 if (sv < 0 || !sv)
11872 return sv;
11873
11874 return isl_map_is_injective(map);
11875}
11876
11877isl_bool isl_set_is_singleton(__isl_keep isl_set *set)
11878{
11879 return isl_map_is_single_valued(set_to_map(set));
11880}
11881
11882/* Does "map" only map elements to themselves?
11883 *
11884 * If the domain and range spaces are different, then "map"
11885 * is considered not to be an identity relation, even if it is empty.
11886 * Otherwise, construct the maximal identity relation and
11887 * check whether "map" is a subset of this relation.
11888 */
11889isl_bool isl_map_is_identity(__isl_keep isl_map *map)
11890{
11891 isl_map *id;
11892 isl_bool equal, is_identity;
11893
11894 equal = isl_map_tuple_is_equal(map, isl_dim_in, map, isl_dim_out);
11895 if (equal < 0 || !equal)
11896 return equal;
11897
11898 id = isl_map_identity(isl_map_get_space(map));
11899 is_identity = isl_map_is_subset(map, id);
11900 isl_map_free(id);
11901
11902 return is_identity;
11903}
11904
11905int isl_map_is_translation(__isl_keep isl_map *map)
11906{
11907 int ok;
11908 isl_set *delta;
11909
11910 delta = isl_map_deltas(isl_map_copy(map));
11911 ok = isl_set_is_singleton(delta);
11912 isl_set_free(delta);
11913
11914 return ok;
11915}
11916
11917static int unique(isl_int *p, unsigned pos, unsigned len)
11918{
11919 if (isl_seq_first_non_zero(p, pos) != -1)
11920 return 0;
11921 if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
11922 return 0;
11923 return 1;
11924}
11925
11926isl_bool isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
11927{
11928 int i, j;
11929 isl_size nvar, n_div;
11930 unsigned ovar;
11931
11932 n_div = isl_basic_set_dim(bset, isl_dim_div);
11933 if (n_div < 0)
11934 return isl_bool_error;
11935 if (n_div != 0)
11936 return isl_bool_false;
11937
11938 nvar = isl_basic_set_dim(bset, isl_dim_set);
11939 if (nvar < 0)
11940 return isl_bool_error;
11941 ovar = isl_space_offset(bset->dim, isl_dim_set);
11942 for (j = 0; j < nvar; ++j) {
11943 int lower = 0, upper = 0;
11944 for (i = 0; i < bset->n_eq; ++i) {
11945 if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
11946 continue;
11947 if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
11948 return isl_bool_false;
11949 break;
11950 }
11951 if (i < bset->n_eq)
11952 continue;
11953 for (i = 0; i < bset->n_ineq; ++i) {
11954 if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
11955 continue;
11956 if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
11957 return isl_bool_false;
11958 if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
11959 lower = 1;
11960 else
11961 upper = 1;
11962 }
11963 if (!lower || !upper)
11964 return isl_bool_false;
11965 }
11966
11967 return isl_bool_true;
11968}
11969
11970isl_bool isl_set_is_box(__isl_keep isl_set *set)
11971{
11972 if (!set)
11973 return isl_bool_error;
11974 if (set->n != 1)
11975 return isl_bool_false;
11976
11977 return isl_basic_set_is_box(set->p[0]);
11978}
11979
11980isl_bool isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
11981{
11982 if (!bset)
11983 return isl_bool_error;
11984
11985 return isl_space_is_wrapping(bset->dim);
11986}
11987
11988isl_bool isl_set_is_wrapping(__isl_keep isl_set *set)
11989{
11990 if (!set)
11991 return isl_bool_error;
11992
11993 return isl_space_is_wrapping(set->dim);
11994}
11995
11996/* Modify the space of "map" through a call to "change".
11997 * If "can_change" is set (not NULL), then first call it to check
11998 * if the modification is allowed, printing the error message "cannot_change"
11999 * if it is not.
12000 */
12001static __isl_give isl_map *isl_map_change_space(__isl_take isl_map *map,
12002 isl_bool (*can_change)(__isl_keep isl_map *map),
12003 const char *cannot_change,
12004 __isl_give isl_space *(*change)(__isl_take isl_space *space))
12005{
12006 isl_bool ok;
12007 isl_space *space;
12008
12009 if (!map)
12010 return NULL;
12011
12012 ok = can_change ? can_change(map) : isl_bool_true;
12013 if (ok < 0)
12014 return isl_map_free(map);
12015 if (!ok)
12016 isl_die(isl_map_get_ctx(map), isl_error_invalid, cannot_change,
12017 return isl_map_free(map));
12018
12019 space = change(isl_map_get_space(map));
12020 map = isl_map_reset_space(map, space);
12021
12022 return map;
12023}
12024
12025/* Is the domain of "map" a wrapped relation?
12026 */
12027isl_bool isl_map_domain_is_wrapping(__isl_keep isl_map *map)
12028{
12029 if (!map)
12030 return isl_bool_error;
12031
12032 return isl_space_domain_is_wrapping(map->dim);
12033}
12034
12035/* Does "map" have a wrapped relation in both domain and range?
12036 */
12037isl_bool isl_map_is_product(__isl_keep isl_map *map)
12038{
12039 return isl_space_is_product(isl_map_peek_space(map));
12040}
12041
12042/* Is the range of "map" a wrapped relation?
12043 */
12044isl_bool isl_map_range_is_wrapping(__isl_keep isl_map *map)
12045{
12046 if (!map)
12047 return isl_bool_error;
12048
12049 return isl_space_range_is_wrapping(map->dim);
12050}
12051
12052__isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
12053{
12054 isl_space *space;
12055
12056 space = isl_basic_map_take_space(bmap);
12057 space = isl_space_wrap(space);
12058 bmap = isl_basic_map_restore_space(bmap, space);
12059
12060 bmap = isl_basic_map_finalize(bmap);
12061
12062 return bset_from_bmap(bmap);
12063}
12064
12065/* Given a map A -> B, return the set (A -> B).
12066 */
12067__isl_give isl_set *isl_map_wrap(__isl_take isl_map *map)
12068{
12069 return isl_map_change_space(map, NULL, NULL, &isl_space_wrap);
12070}
12071
12072__isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
12073{
12074 bset = isl_basic_set_cow(bset);
12075 if (!bset)
12076 return NULL;
12077
12078 bset->dim = isl_space_unwrap(bset->dim);
12079 if (!bset->dim)
12080 goto error;
12081
12082 bset = isl_basic_set_finalize(bset);
12083
12084 return bset_to_bmap(bset);
12085error:
12086 isl_basic_set_free(bset);
12087 return NULL;
12088}
12089
12090/* Given a set (A -> B), return the map A -> B.
12091 * Error out if "set" is not of the form (A -> B).
12092 */
12093__isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set)
12094{
12095 return isl_map_change_space(set, &isl_set_is_wrapping,
12096 "not a wrapping set", &isl_space_unwrap);
12097}
12098
12099__isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
12100 enum isl_dim_type type)
12101{
12102 isl_space *space;
12103
12104 space = isl_basic_map_take_space(bmap);
12105 space = isl_space_reset(space, type);
12106 bmap = isl_basic_map_restore_space(bmap, space);
12107
12108 bmap = isl_basic_map_mark_final(bmap);
12109
12110 return bmap;
12111}
12112
12113__isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
12114 enum isl_dim_type type)
12115{
12116 int i;
12117 isl_space *space;
12118
12119 if (!map)
12120 return NULL;
12121
12122 if (!isl_space_is_named_or_nested(map->dim, type))
12123 return map;
12124
12125 map = isl_map_cow(map);
12126 if (!map)
12127 return NULL;
12128
12129 for (i = 0; i < map->n; ++i) {
12130 map->p[i] = isl_basic_map_reset(map->p[i], type);
12131 if (!map->p[i])
12132 goto error;
12133 }
12134
12135 space = isl_map_take_space(map);
12136 space = isl_space_reset(space, type);
12137 map = isl_map_restore_space(map, space);
12138
12139 return map;
12140error:
12141 isl_map_free(map);
12142 return NULL;
12143}
12144
12145__isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
12146{
12147 isl_space *space;
12148
12149 space = isl_basic_map_take_space(bmap);
12150 space = isl_space_flatten(space);
12151 bmap = isl_basic_map_restore_space(bmap, space);
12152
12153 bmap = isl_basic_map_mark_final(bmap);
12154
12155 return bmap;
12156}
12157
12158__isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
12159{
12160 return bset_from_bmap(isl_basic_map_flatten(bset_to_bmap(bset)));
12161}
12162
12163__isl_give isl_basic_map *isl_basic_map_flatten_domain(
12164 __isl_take isl_basic_map *bmap)
12165{
12166 isl_space *space;
12167
12168 space = isl_basic_map_take_space(bmap);
12169 space = isl_space_flatten_domain(space);
12170 bmap = isl_basic_map_restore_space(bmap, space);
12171
12172 bmap = isl_basic_map_mark_final(bmap);
12173
12174 return bmap;
12175}
12176
12177__isl_give isl_basic_map *isl_basic_map_flatten_range(
12178 __isl_take isl_basic_map *bmap)
12179{
12180 isl_space *space;
12181
12182 space = isl_basic_map_take_space(bmap);
12183 space = isl_space_flatten_range(space);
12184 bmap = isl_basic_map_restore_space(bmap, space);
12185
12186 bmap = isl_basic_map_mark_final(bmap);
12187
12188 return bmap;
12189}
12190
12191/* Remove any internal structure from the spaces of domain and range of "map".
12192 */
12193__isl_give isl_map *isl_map_flatten(__isl_take isl_map *map)
12194{
12195 if (!map)
12196 return NULL;
12197
12198 if (!map->dim->nested[0] && !map->dim->nested[1])
12199 return map;
12200
12201 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten);
12202}
12203
12204__isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
12205{
12206 return set_from_map(isl_map_flatten(set_to_map(set)));
12207}
12208
12209__isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
12210{
12211 isl_space *space, *flat_space;
12212 isl_map *map;
12213
12214 space = isl_set_get_space(set);
12215 flat_space = isl_space_flatten(isl_space_copy(space));
12216 map = isl_map_identity(isl_space_join(isl_space_reverse(space),
12217 flat_space));
12218 map = isl_map_intersect_domain(map, set);
12219
12220 return map;
12221}
12222
12223/* Remove any internal structure from the space of the domain of "map".
12224 */
12225__isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map)
12226{
12227 if (!map)
12228 return NULL;
12229
12230 if (!map->dim->nested[0])
12231 return map;
12232
12233 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_domain);
12234}
12235
12236/* Remove any internal structure from the space of the range of "map".
12237 */
12238__isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map)
12239{
12240 if (!map)
12241 return NULL;
12242
12243 if (!map->dim->nested[1])
12244 return map;
12245
12246 return isl_map_change_space(map, NULL, NULL, &isl_space_flatten_range);
12247}
12248
12249/* Reorder the dimensions of "bmap" according to the given dim_map
12250 * and set the dimension specification to "space" and
12251 * perform Gaussian elimination on the result.
12252 */
12253__isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
12254 __isl_take isl_space *space, __isl_take struct isl_dim_map *dim_map)
12255{
12256 isl_basic_map *res;
12257 unsigned flags;
12258 isl_size n_div;
12259
12260 n_div = isl_basic_map_dim(bmap, isl_dim_div);
12261 if (n_div < 0 || !space || !dim_map)
12262 goto error;
12263
12264 flags = bmap->flags;
12265 ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
12266 ISL_FL_CLR(flags, ISL_BASIC_MAP_SORTED);
12267 ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
12268 res = isl_basic_map_alloc_space(space, n_div, bmap->n_eq, bmap->n_ineq);
12269 res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
12270 if (res)
12271 res->flags = flags;
12272 res = isl_basic_map_gauss(res, NULL);
12273 res = isl_basic_map_finalize(res);
12274 return res;
12275error:
12276 isl_dim_map_free(dim_map);
12277 isl_basic_map_free(bmap);
12278 isl_space_free(space);
12279 return NULL;
12280}
12281
12282/* Reorder the dimensions of "map" according to given reordering.
12283 */
12284__isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
12285 __isl_take isl_reordering *r)
12286{
12287 int i;
12288 struct isl_dim_map *dim_map;
12289
12290 map = isl_map_cow(map);
12291 dim_map = isl_dim_map_from_reordering(r);
12292 if (!map || !r || !dim_map)
12293 goto error;
12294
12295 for (i = 0; i < map->n; ++i) {
12296 struct isl_dim_map *dim_map_i;
12297 isl_space *space;
12298
12299 dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
12300
12301 space = isl_reordering_get_space(r);
12302 map->p[i] = isl_basic_map_realign(map->p[i], space, dim_map_i);
12303
12304 if (!map->p[i])
12305 goto error;
12306 }
12307
12308 map = isl_map_reset_space(map, isl_reordering_get_space(r));
12309 map = isl_map_unmark_normalized(map);
12310
12311 isl_reordering_free(r);
12312 isl_dim_map_free(dim_map);
12313 return map;
12314error:
12315 isl_dim_map_free(dim_map);
12316 isl_map_free(map);
12317 isl_reordering_free(r);
12318 return NULL;
12319}
12320
12321__isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
12322 __isl_take isl_reordering *r)
12323{
12324 return set_from_map(isl_map_realign(set_to_map(set), r));
12325}
12326
12327__isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
12328 __isl_take isl_space *model)
12329{
12330 isl_ctx *ctx;
12331 isl_bool aligned;
12332
12333 if (!map || !model)
12334 goto error;
12335
12336 ctx = isl_space_get_ctx(model);
12337 if (!isl_space_has_named_params(model))
12338 isl_die(ctx, isl_error_invalid,
12339 "model has unnamed parameters", goto error);
12340 if (isl_map_check_named_params(map) < 0)
12341 goto error;
12342 aligned = isl_map_space_has_equal_params(map, model);
12343 if (aligned < 0)
12344 goto error;
12345 if (!aligned) {
12346 isl_reordering *exp;
12347
12348 exp = isl_parameter_alignment_reordering(map->dim, model);
12349 exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
12350 map = isl_map_realign(map, exp);
12351 }
12352
12353 isl_space_free(model);
12354 return map;
12355error:
12356 isl_space_free(model);
12357 isl_map_free(map);
12358 return NULL;
12359}
12360
12361__isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
12362 __isl_take isl_space *model)
12363{
12364 return isl_map_align_params(set, model);
12365}
12366
12367/* Align the parameters of "bmap" to those of "model", introducing
12368 * additional parameters if needed.
12369 */
12370__isl_give isl_basic_map *isl_basic_map_align_params(
12371 __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
12372{
12373 isl_ctx *ctx;
12374 isl_bool equal_params;
12375
12376 if (!bmap || !model)
12377 goto error;
12378
12379 ctx = isl_space_get_ctx(model);
12380 if (!isl_space_has_named_params(model))
12381 isl_die(ctx, isl_error_invalid,
12382 "model has unnamed parameters", goto error);
12383 if (isl_basic_map_check_named_params(bmap) < 0)
12384 goto error;
12385 equal_params = isl_space_has_equal_params(bmap->dim, model);
12386 if (equal_params < 0)
12387 goto error;
12388 if (!equal_params) {
12389 isl_reordering *exp;
12390 struct isl_dim_map *dim_map;
12391
12392 exp = isl_parameter_alignment_reordering(bmap->dim, model);
12393 exp = isl_reordering_extend_space(exp,
12394 isl_basic_map_get_space(bmap));
12395 dim_map = isl_dim_map_from_reordering(exp);
12396 bmap = isl_basic_map_realign(bmap,
12397 isl_reordering_get_space(exp),
12398 isl_dim_map_extend(dim_map, bmap));
12399 isl_reordering_free(exp);
12400 isl_dim_map_free(dim_map);
12401 }
12402
12403 isl_space_free(model);
12404 return bmap;
12405error:
12406 isl_space_free(model);
12407 isl_basic_map_free(bmap);
12408 return NULL;
12409}
12410
12411/* Do "bset" and "space" have the same parameters?
12412 */
12413isl_bool isl_basic_set_space_has_equal_params(__isl_keep isl_basic_set *bset,
12414 __isl_keep isl_space *space)
12415{
12416 isl_space *bset_space;
12417
12418 bset_space = isl_basic_set_peek_space(bset);
12419 return isl_space_has_equal_params(bset_space, space);
12420}
12421
12422/* Do "map" and "space" have the same parameters?
12423 */
12424isl_bool isl_map_space_has_equal_params(__isl_keep isl_map *map,
12425 __isl_keep isl_space *space)
12426{
12427 isl_space *map_space;
12428
12429 map_space = isl_map_peek_space(map);
12430 return isl_space_has_equal_params(map_space, space);
12431}
12432
12433/* Do "set" and "space" have the same parameters?
12434 */
12435isl_bool isl_set_space_has_equal_params(__isl_keep isl_set *set,
12436 __isl_keep isl_space *space)
12437{
12438 return isl_map_space_has_equal_params(set_to_map(set), space);
12439}
12440
12441/* Align the parameters of "bset" to those of "model", introducing
12442 * additional parameters if needed.
12443 */
12444__isl_give isl_basic_set *isl_basic_set_align_params(
12445 __isl_take isl_basic_set *bset, __isl_take isl_space *model)
12446{
12447 return isl_basic_map_align_params(bset, model);
12448}
12449
12450/* Drop all parameters not referenced by "map".
12451 */
12452__isl_give isl_map *isl_map_drop_unused_params(__isl_take isl_map *map)
12453{
12454 int i;
12455 isl_size n;
12456
12457 n = isl_map_dim(map, isl_dim_param);
12458 if (isl_map_check_named_params(map) < 0 || n < 0)
12459 return isl_map_free(map);
12460
12461 for (i = n - 1; i >= 0; i--) {
12462 isl_bool involves;
12463
12464 involves = isl_map_involves_dims(map, isl_dim_param, i, 1);
12465 if (involves < 0)
12466 return isl_map_free(map);
12467 if (!involves)
12468 map = isl_map_project_out(map, isl_dim_param, i, 1);
12469 }
12470
12471 return map;
12472}
12473
12474/* Drop all parameters not referenced by "set".
12475 */
12476__isl_give isl_set *isl_set_drop_unused_params(
12477 __isl_take isl_set *set)
12478{
12479 return set_from_map(isl_map_drop_unused_params(set_to_map(set)));
12480}
12481
12482/* Drop all parameters not referenced by "bmap".
12483 */
12484__isl_give isl_basic_map *isl_basic_map_drop_unused_params(
12485 __isl_take isl_basic_map *bmap)
12486{
12487 isl_size nparam;
12488 int i;
12489
12490 nparam = isl_basic_map_dim(bmap, isl_dim_param);
12491 if (nparam < 0 || isl_basic_map_check_named_params(bmap) < 0)
12492 return isl_basic_map_free(bmap);
12493
12494 for (i = nparam - 1; i >= 0; i--) {
12495 isl_bool involves;
12496
12497 involves = isl_basic_map_involves_dims(bmap,
12498 isl_dim_param, i, 1);
12499 if (involves < 0)
12500 return isl_basic_map_free(bmap);
12501 if (!involves)
12502 bmap = isl_basic_map_drop(bmap, isl_dim_param, i, 1);
12503 }
12504
12505 return bmap;
12506}
12507
12508/* Drop all parameters not referenced by "bset".
12509 */
12510__isl_give isl_basic_set *isl_basic_set_drop_unused_params(
12511 __isl_take isl_basic_set *bset)
12512{
12513 return bset_from_bmap(isl_basic_map_drop_unused_params(
12514 bset_to_bmap(bset)));
12515}
12516
12517/* Given a tuple of identifiers "tuple" in a space that corresponds
12518 * to that of "set", if any of those identifiers appear as parameters
12519 * in "set", then equate those parameters with the corresponding
12520 * set dimensions and project out the parameters.
12521 * The result therefore has no such parameters.
12522 */
12523static __isl_give isl_set *equate_params(__isl_take isl_set *set,
12524 __isl_keep isl_multi_id *tuple)
12525{
12526 int i;
12527 isl_size n;
12528 isl_space *set_space, *tuple_space;
12529
12530 set_space = isl_set_peek_space(set);
12531 tuple_space = isl_multi_id_peek_space(tuple);
12532 if (isl_space_check_equal_tuples(tuple_space, set_space) < 0)
12533 return isl_set_free(set);
12534 n = isl_multi_id_size(tuple);
12535 if (n < 0)
12536 return isl_set_free(set);
12537 for (i = 0; i < n; ++i) {
12538 isl_id *id;
12539 int pos;
12540
12541 id = isl_multi_id_get_at(tuple, i);
12542 if (!id)
12543 return isl_set_free(set);
12544 pos = isl_set_find_dim_by_id(set, isl_dim_param, id);
12545 isl_id_free(id);
12546 if (pos < 0)
12547 continue;
12548 set = isl_set_equate(set, isl_dim_param, pos, isl_dim_set, i);
12549 set = isl_set_project_out(set, isl_dim_param, pos, 1);
12550 }
12551 return set;
12552}
12553
12554/* Bind the set dimensions of "set" to parameters with identifiers
12555 * specified by "tuple", living in the same space as "set".
12556 *
12557 * If no parameters with these identifiers appear in "set" already,
12558 * then the set dimensions are simply reinterpreted as parameters.
12559 * Otherwise, the parameters are first equated to the corresponding
12560 * set dimensions.
12561 */
12562__isl_give isl_set *isl_set_bind(__isl_take isl_set *set,
12563 __isl_take isl_multi_id *tuple)
12564{
12565 isl_space *space;
12566
12567 set = equate_params(set, tuple);
12568 space = isl_set_get_space(set);
12569 space = isl_space_bind_set(space, tuple);
12570 isl_multi_id_free(tuple);
12571 set = isl_set_reset_space(set, space);
12572
12573 return set;
12574}
12575
12576/* Given a tuple of identifiers "tuple" in a space that corresponds
12577 * to the domain of "map", if any of those identifiers appear as parameters
12578 * in "map", then equate those parameters with the corresponding
12579 * input dimensions and project out the parameters.
12580 * The result therefore has no such parameters.
12581 */
12582static __isl_give isl_map *map_equate_params(__isl_take isl_map *map,
12583 __isl_keep isl_multi_id *tuple)
12584{
12585 int i;
12586 isl_size n;
12587 isl_space *map_space, *tuple_space;
12588
12589 map_space = isl_map_peek_space(map);
12590 tuple_space = isl_multi_id_peek_space(tuple);
12591 if (isl_space_check_domain_tuples(tuple_space, map_space) < 0)
12592 return isl_map_free(map);
12593 n = isl_multi_id_size(tuple);
12594 if (n < 0)
12595 return isl_map_free(map);
12596 for (i = 0; i < n; ++i) {
12597 isl_id *id;
12598 int pos;
12599
12600 id = isl_multi_id_get_at(tuple, i);
12601 if (!id)
12602 return isl_map_free(map);
12603 pos = isl_map_find_dim_by_id(map, isl_dim_param, id);
12604 isl_id_free(id);
12605 if (pos < 0)
12606 continue;
12607 map = isl_map_equate(map, isl_dim_param, pos, isl_dim_in, i);
12608 map = isl_map_project_out(map, isl_dim_param, pos, 1);
12609 }
12610 return map;
12611}
12612
12613/* Bind the input dimensions of "map" to parameters with identifiers
12614 * specified by "tuple", living in the domain space of "map".
12615 *
12616 * If no parameters with these identifiers appear in "map" already,
12617 * then the input dimensions are simply reinterpreted as parameters.
12618 * Otherwise, the parameters are first equated to the corresponding
12619 * input dimensions.
12620 */
12621__isl_give isl_set *isl_map_bind_domain(__isl_take isl_map *map,
12622 __isl_take isl_multi_id *tuple)
12623{
12624 isl_space *space;
12625 isl_set *set;
12626
12627 map = map_equate_params(map, tuple);
12628 space = isl_map_get_space(map);
12629 space = isl_space_bind_map_domain(space, tuple);
12630 isl_multi_id_free(tuple);
12631 set = set_from_map(isl_map_reset_space(map, space));
12632
12633 return set;
12634}
12635
12636/* Bind the output dimensions of "map" to parameters with identifiers
12637 * specified by "tuple", living in the range space of "map".
12638 *
12639 * Since binding is more easily implemented on the domain,
12640 * bind the input dimensions of the inverse of "map".
12641 */
12642__isl_give isl_set *isl_map_bind_range(__isl_take isl_map *map,
12643 __isl_take isl_multi_id *tuple)
12644{
12645 return isl_map_bind_domain(isl_map_reverse(map), tuple);
12646}
12647
12648/* Insert a domain corresponding to "tuple"
12649 * into the nullary or unary relation "set".
12650 * The result has an extra initial tuple and is therefore
12651 * either a unary or binary relation.
12652 * Any parameters with identifiers in "tuple" are reinterpreted
12653 * as the corresponding domain dimensions.
12654 */
12655static __isl_give isl_map *unbind_params_insert_domain(
12656 __isl_take isl_set *set, __isl_take isl_multi_id *tuple)
12657{
12658 isl_space *space;
12659 isl_reordering *r;
12660
12661 space = isl_set_peek_space(set);
12662 r = isl_reordering_unbind_params_insert_domain(space, tuple);
12663 isl_multi_id_free(tuple);
12664
12665 return isl_map_realign(set_to_map(set), r);
12666}
12667
12668/* Construct a set with "tuple" as domain from the parameter domain "set".
12669 * Any parameters with identifiers in "tuple" are reinterpreted
12670 * as the corresponding set dimensions.
12671 */
12672__isl_give isl_set *isl_set_unbind_params(__isl_take isl_set *set,
12673 __isl_take isl_multi_id *tuple)
12674{
12675 isl_bool is_params;
12676
12677 is_params = isl_set_is_params(set);
12678 if (is_params < 0)
12679 set = isl_set_free(set);
12680 else if (!is_params)
12681 isl_die(isl_set_get_ctx(set), isl_error_invalid,
12682 "expecting parameter domain", set = isl_set_free(set));
12683 return set_from_map(unbind_params_insert_domain(set, tuple));
12684}
12685
12686/* Check that "set" is a proper set, i.e., that it is not a parameter domain.
12687 */
12688static isl_stat isl_set_check_is_set(__isl_keep isl_set *set)
12689{
12690 isl_bool is_params;
12691
12692 is_params = isl_set_is_params(set);
12693 if (is_params < 0)
12694 return isl_stat_error;
12695 else if (is_params)
12696 isl_die(isl_set_get_ctx(set), isl_error_invalid,
12697 "expecting proper set", return isl_stat_error);
12698
12699 return isl_stat_ok;
12700}
12701
12702/* Construct a map with "domain" as domain and "set" as range.
12703 * Any parameters with identifiers in "domain" are reinterpreted
12704 * as the corresponding domain dimensions.
12705 */
12706__isl_give isl_map *isl_set_unbind_params_insert_domain(
12707 __isl_take isl_set *set, __isl_take isl_multi_id *domain)
12708{
12709 if (isl_set_check_is_set(set) < 0)
12710 set = isl_set_free(set);
12711 return unbind_params_insert_domain(set, domain);
12712}
12713
12714/* Construct a map with "domain" as domain and "set" as range.
12715 */
12716__isl_give isl_map *isl_set_insert_domain(__isl_take isl_set *set,
12717 __isl_take isl_space *domain)
12718{
12719 isl_size dim;
12720 isl_space *space;
12721 isl_map *map;
12722
12723 if (isl_set_check_is_set(set) < 0 || isl_space_check_is_set(domain) < 0)
12724 domain = isl_space_free(domain);
12725 dim = isl_space_dim(domain, isl_dim_set);
12726 if (dim < 0)
12727 domain = isl_space_free(domain);
12728 space = isl_set_get_space(set);
12729 domain = isl_space_replace_params(domain, space);
12730 space = isl_space_map_from_domain_and_range(domain, space);
12731
12732 map = isl_map_from_range(set);
12733 map = isl_map_add_dims(map, isl_dim_in, dim);
12734 map = isl_map_reset_space(map, space);
12735
12736 return map;
12737}
12738
12739__isl_give isl_mat *isl_basic_map_equalities_matrix(
12740 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12741 enum isl_dim_type c2, enum isl_dim_type c3,
12742 enum isl_dim_type c4, enum isl_dim_type c5)
12743{
12744 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12745 struct isl_mat *mat;
12746 int i, j, k;
12747 int pos;
12748 isl_size total;
12749
12750 total = isl_basic_map_dim(bmap, isl_dim_all);
12751 if (total < 0)
12752 return NULL;
12753 mat = isl_mat_alloc(bmap->ctx, bmap->n_eq, total + 1);
12754 if (!mat)
12755 return NULL;
12756 for (i = 0; i < bmap->n_eq; ++i)
12757 for (j = 0, pos = 0; j < 5; ++j) {
12758 int off = isl_basic_map_offset(bmap, c[j]);
12759 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12760 if (dim < 0)
12761 return isl_mat_free(mat);
12762 for (k = 0; k < dim; ++k) {
12763 isl_int_set(mat->row[i][pos],
12764 bmap->eq[i][off + k]);
12765 ++pos;
12766 }
12767 }
12768
12769 return mat;
12770}
12771
12772__isl_give isl_mat *isl_basic_map_inequalities_matrix(
12773 __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
12774 enum isl_dim_type c2, enum isl_dim_type c3,
12775 enum isl_dim_type c4, enum isl_dim_type c5)
12776{
12777 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12778 struct isl_mat *mat;
12779 int i, j, k;
12780 int pos;
12781 isl_size total;
12782
12783 total = isl_basic_map_dim(bmap, isl_dim_all);
12784 if (total < 0)
12785 return NULL;
12786 mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq, total + 1);
12787 if (!mat)
12788 return NULL;
12789 for (i = 0; i < bmap->n_ineq; ++i)
12790 for (j = 0, pos = 0; j < 5; ++j) {
12791 int off = isl_basic_map_offset(bmap, c[j]);
12792 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12793 if (dim < 0)
12794 return isl_mat_free(mat);
12795 for (k = 0; k < dim; ++k) {
12796 isl_int_set(mat->row[i][pos],
12797 bmap->ineq[i][off + k]);
12798 ++pos;
12799 }
12800 }
12801
12802 return mat;
12803}
12804
12805__isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
12806 __isl_take isl_space *space,
12807 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12808 enum isl_dim_type c2, enum isl_dim_type c3,
12809 enum isl_dim_type c4, enum isl_dim_type c5)
12810{
12811 enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
12812 isl_basic_map *bmap = NULL;
12813 isl_size dim;
12814 unsigned total;
12815 unsigned extra;
12816 int i, j, k, l;
12817 int pos;
12818
12819 dim = isl_space_dim(space, isl_dim_all);
12820 if (dim < 0 || !eq || !ineq)
12821 goto error;
12822
12823 if (eq->n_col != ineq->n_col)
12824 isl_die(space->ctx, isl_error_invalid,
12825 "equalities and inequalities matrices should have "
12826 "same number of columns", goto error);
12827
12828 total = 1 + dim;
12829
12830 if (eq->n_col < total)
12831 isl_die(space->ctx, isl_error_invalid,
12832 "number of columns too small", goto error);
12833
12834 extra = eq->n_col - total;
12835
12836 bmap = isl_basic_map_alloc_space(isl_space_copy(space), extra,
12837 eq->n_row, ineq->n_row);
12838 if (!bmap)
12839 goto error;
12840 for (i = 0; i < extra; ++i) {
12841 k = isl_basic_map_alloc_div(bmap);
12842 if (k < 0)
12843 goto error;
12844 isl_int_set_si(bmap->div[k][0], 0);
12845 }
12846 for (i = 0; i < eq->n_row; ++i) {
12847 l = isl_basic_map_alloc_equality(bmap);
12848 if (l < 0)
12849 goto error;
12850 for (j = 0, pos = 0; j < 5; ++j) {
12851 int off = isl_basic_map_offset(bmap, c[j]);
12852 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12853 if (dim < 0)
12854 goto error;
12855 for (k = 0; k < dim; ++k) {
12856 isl_int_set(bmap->eq[l][off + k],
12857 eq->row[i][pos]);
12858 ++pos;
12859 }
12860 }
12861 }
12862 for (i = 0; i < ineq->n_row; ++i) {
12863 l = isl_basic_map_alloc_inequality(bmap);
12864 if (l < 0)
12865 goto error;
12866 for (j = 0, pos = 0; j < 5; ++j) {
12867 int off = isl_basic_map_offset(bmap, c[j]);
12868 isl_size dim = isl_basic_map_dim(bmap, c[j]);
12869 if (dim < 0)
12870 goto error;
12871 for (k = 0; k < dim; ++k) {
12872 isl_int_set(bmap->ineq[l][off + k],
12873 ineq->row[i][pos]);
12874 ++pos;
12875 }
12876 }
12877 }
12878
12879 isl_space_free(space);
12880 isl_mat_free(eq);
12881 isl_mat_free(ineq);
12882
12883 bmap = isl_basic_map_simplify(bmap);
12884 return isl_basic_map_finalize(bmap);
12885error:
12886 isl_space_free(space);
12887 isl_mat_free(eq);
12888 isl_mat_free(ineq);
12889 isl_basic_map_free(bmap);
12890 return NULL;
12891}
12892
12893__isl_give isl_mat *isl_basic_set_equalities_matrix(
12894 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12895 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12896{
12897 return isl_basic_map_equalities_matrix(bset_to_bmap(bset),
12898 c1, c2, c3, c4, isl_dim_in);
12899}
12900
12901__isl_give isl_mat *isl_basic_set_inequalities_matrix(
12902 __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
12903 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12904{
12905 return isl_basic_map_inequalities_matrix(bset_to_bmap(bset),
12906 c1, c2, c3, c4, isl_dim_in);
12907}
12908
12909__isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
12910 __isl_take isl_space *space,
12911 __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
12912 enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
12913{
12914 isl_basic_map *bmap;
12915 bmap = isl_basic_map_from_constraint_matrices(space, eq, ineq,
12916 c1, c2, c3, c4, isl_dim_in);
12917 return bset_from_bmap(bmap);
12918}
12919
12920isl_bool isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
12921{
12922 if (!bmap)
12923 return isl_bool_error;
12924
12925 return isl_space_can_zip(bmap->dim);
12926}
12927
12928isl_bool isl_map_can_zip(__isl_keep isl_map *map)
12929{
12930 if (!map)
12931 return isl_bool_error;
12932
12933 return isl_space_can_zip(map->dim);
12934}
12935
12936/* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
12937 * (A -> C) -> (B -> D).
12938 */
12939__isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
12940{
12941 unsigned pos;
12942 isl_size n_in;
12943 isl_size n1;
12944 isl_size n2;
12945
12946 if (!bmap)
12947 return NULL;
12948
12949 if (!isl_basic_map_can_zip(bmap))
12950 isl_die(bmap->ctx, isl_error_invalid,
12951 "basic map cannot be zipped", goto error);
12952 n_in = isl_space_dim(bmap->dim->nested[0], isl_dim_in);
12953 n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
12954 n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
12955 if (n_in < 0 || n1 < 0 || n2 < 0)
12956 return isl_basic_map_free(bmap);
12957 pos = isl_basic_map_offset(bmap, isl_dim_in) + n_in;
12958 bmap = isl_basic_map_cow(bmap);
12959 bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
12960 if (!bmap)
12961 return NULL;
12962 bmap->dim = isl_space_zip(bmap->dim);
12963 if (!bmap->dim)
12964 goto error;
12965 bmap = isl_basic_map_mark_final(bmap);
12966 return bmap;
12967error:
12968 isl_basic_map_free(bmap);
12969 return NULL;
12970}
12971
12972/* Given a map (A -> B) -> (C -> D), return the corresponding map
12973 * (A -> C) -> (B -> D).
12974 */
12975__isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
12976{
12977 if (!map)
12978 return NULL;
12979
12980 if (!isl_map_can_zip(map))
12981 isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
12982 goto error);
12983
12984 return isl_map_transform(map, &isl_space_zip, &isl_basic_map_zip);
12985error:
12986 isl_map_free(map);
12987 return NULL;
12988}
12989
12990/* Can we apply isl_basic_map_curry to "bmap"?
12991 * That is, does it have a nested relation in its domain?
12992 */
12993isl_bool isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
12994{
12995 if (!bmap)
12996 return isl_bool_error;
12997
12998 return isl_space_can_curry(bmap->dim);
12999}
13000
13001/* Can we apply isl_map_curry to "map"?
13002 * That is, does it have a nested relation in its domain?
13003 */
13004isl_bool isl_map_can_curry(__isl_keep isl_map *map)
13005{
13006 if (!map)
13007 return isl_bool_error;
13008
13009 return isl_space_can_curry(map->dim);
13010}
13011
13012/* Given a basic map (A -> B) -> C, return the corresponding basic map
13013 * A -> (B -> C).
13014 */
13015__isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
13016{
13017
13018 if (!bmap)
13019 return NULL;
13020
13021 if (!isl_basic_map_can_curry(bmap))
13022 isl_die(bmap->ctx, isl_error_invalid,
13023 "basic map cannot be curried", goto error);
13024 bmap = isl_basic_map_cow(bmap);
13025 if (!bmap)
13026 return NULL;
13027 bmap->dim = isl_space_curry(bmap->dim);
13028 if (!bmap->dim)
13029 goto error;
13030 bmap = isl_basic_map_mark_final(bmap);
13031 return bmap;
13032error:
13033 isl_basic_map_free(bmap);
13034 return NULL;
13035}
13036
13037/* Given a map (A -> B) -> C, return the corresponding map
13038 * A -> (B -> C).
13039 */
13040__isl_give isl_map *isl_map_curry(__isl_take isl_map *map)
13041{
13042 return isl_map_change_space(map, &isl_map_can_curry,
13043 "map cannot be curried", &isl_space_curry);
13044}
13045
13046/* Can isl_map_range_curry be applied to "map"?
13047 * That is, does it have a nested relation in its range,
13048 * the domain of which is itself a nested relation?
13049 */
13050isl_bool isl_map_can_range_curry(__isl_keep isl_map *map)
13051{
13052 if (!map)
13053 return isl_bool_error;
13054
13055 return isl_space_can_range_curry(map->dim);
13056}
13057
13058/* Given a map A -> ((B -> C) -> D), return the corresponding map
13059 * A -> (B -> (C -> D)).
13060 */
13061__isl_give isl_map *isl_map_range_curry(__isl_take isl_map *map)
13062{
13063 return isl_map_change_space(map, &isl_map_can_range_curry,
13064 "map range cannot be curried",
13065 &isl_space_range_curry);
13066}
13067
13068/* Can we apply isl_basic_map_uncurry to "bmap"?
13069 * That is, does it have a nested relation in its domain?
13070 */
13071isl_bool isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
13072{
13073 if (!bmap)
13074 return isl_bool_error;
13075
13076 return isl_space_can_uncurry(bmap->dim);
13077}
13078
13079/* Can we apply isl_map_uncurry to "map"?
13080 * That is, does it have a nested relation in its domain?
13081 */
13082isl_bool isl_map_can_uncurry(__isl_keep isl_map *map)
13083{
13084 if (!map)
13085 return isl_bool_error;
13086
13087 return isl_space_can_uncurry(map->dim);
13088}
13089
13090/* Given a basic map A -> (B -> C), return the corresponding basic map
13091 * (A -> B) -> C.
13092 */
13093__isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
13094{
13095
13096 if (!bmap)
13097 return NULL;
13098
13099 if (!isl_basic_map_can_uncurry(bmap))
13100 isl_die(bmap->ctx, isl_error_invalid,
13101 "basic map cannot be uncurried",
13102 return isl_basic_map_free(bmap));
13103 bmap = isl_basic_map_cow(bmap);
13104 if (!bmap)
13105 return NULL;
13106 bmap->dim = isl_space_uncurry(bmap->dim);
13107 if (!bmap->dim)
13108 return isl_basic_map_free(bmap);
13109 bmap = isl_basic_map_mark_final(bmap);
13110 return bmap;
13111}
13112
13113/* Given a map A -> (B -> C), return the corresponding map
13114 * (A -> B) -> C.
13115 */
13116__isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map)
13117{
13118 return isl_map_change_space(map, &isl_map_can_uncurry,
13119 "map cannot be uncurried", &isl_space_uncurry);
13120}
13121
13122__isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
13123 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13124{
13125 return isl_map_equate(set, type1, pos1, type2, pos2);
13126}
13127
13128/* Construct a basic map where the given dimensions are equal to each other.
13129 */
13130static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
13131 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13132{
13133 isl_basic_map *bmap = NULL;
13134 int i;
13135 isl_size total;
13136
13137 total = isl_space_dim(space, isl_dim_all);
13138 if (total < 0 ||
13139 isl_space_check_range(space, type1, pos1, 1) < 0 ||
13140 isl_space_check_range(space, type2, pos2, 1) < 0)
13141 goto error;
13142
13143 if (type1 == type2 && pos1 == pos2)
13144 return isl_basic_map_universe(space);
13145
13146 bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
13147 i = isl_basic_map_alloc_equality(bmap);
13148 if (i < 0)
13149 goto error;
13150 isl_seq_clr(bmap->eq[i], 1 + total);
13151 pos1 += isl_basic_map_offset(bmap, type1);
13152 pos2 += isl_basic_map_offset(bmap, type2);
13153 isl_int_set_si(bmap->eq[i][pos1], -1);
13154 isl_int_set_si(bmap->eq[i][pos2], 1);
13155 bmap = isl_basic_map_finalize(bmap);
13156 isl_space_free(space);
13157 return bmap;
13158error:
13159 isl_space_free(space);
13160 isl_basic_map_free(bmap);
13161 return NULL;
13162}
13163
13164/* Add a constraint imposing that the given two dimensions are equal.
13165 */
13166__isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
13167 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13168{
13169 isl_basic_map *eq;
13170
13171 eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13172
13173 bmap = isl_basic_map_intersect(bmap, eq);
13174
13175 return bmap;
13176}
13177
13178/* Add a constraint imposing that the given two dimensions are equal.
13179 */
13180__isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
13181 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13182{
13183 isl_basic_map *bmap;
13184
13185 bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
13186
13187 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13188
13189 return map;
13190}
13191
13192/* Add a constraint imposing that the given two dimensions have opposite values.
13193 */
13194__isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
13195 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13196{
13197 isl_basic_map *bmap = NULL;
13198 int i;
13199 isl_size total;
13200
13201 if (isl_map_check_range(map, type1, pos1, 1) < 0)
13202 return isl_map_free(map);
13203 if (isl_map_check_range(map, type2, pos2, 1) < 0)
13204 return isl_map_free(map);
13205
13206 total = isl_map_dim(map, isl_dim_all);
13207 if (total < 0)
13208 return isl_map_free(map);
13209 bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
13210 i = isl_basic_map_alloc_equality(bmap);
13211 if (i < 0)
13212 goto error;
13213 isl_seq_clr(bmap->eq[i], 1 + total);
13214 pos1 += isl_basic_map_offset(bmap, type1);
13215 pos2 += isl_basic_map_offset(bmap, type2);
13216 isl_int_set_si(bmap->eq[i][pos1], 1);
13217 isl_int_set_si(bmap->eq[i][pos2], 1);
13218 bmap = isl_basic_map_finalize(bmap);
13219
13220 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13221
13222 return map;
13223error:
13224 isl_basic_map_free(bmap);
13225 isl_map_free(map);
13226 return NULL;
13227}
13228
13229/* Construct a constraint imposing that the value of the first dimension is
13230 * greater than or equal to that of the second.
13231 */
13232static __isl_give isl_constraint *constraint_order_ge(
13233 __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
13234 enum isl_dim_type type2, int pos2)
13235{
13236 isl_constraint *c;
13237
13238 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13239 isl_space_check_range(space, type2, pos2, 1) < 0)
13240 space = isl_space_free(space);
13241 if (!space)
13242 return NULL;
13243
13244 c = isl_constraint_alloc_inequality(isl_local_space_from_space(space));
13245
13246 if (type1 == type2 && pos1 == pos2)
13247 return c;
13248
13249 c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
13250 c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
13251
13252 return c;
13253}
13254
13255/* Add a constraint imposing that the value of the first dimension is
13256 * greater than or equal to that of the second.
13257 */
13258__isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
13259 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13260{
13261 isl_constraint *c;
13262 isl_space *space;
13263
13264 if (type1 == type2 && pos1 == pos2)
13265 return bmap;
13266 space = isl_basic_map_get_space(bmap);
13267 c = constraint_order_ge(space, type1, pos1, type2, pos2);
13268 bmap = isl_basic_map_add_constraint(bmap, c);
13269
13270 return bmap;
13271}
13272
13273/* Add a constraint imposing that the value of the first dimension is
13274 * greater than or equal to that of the second.
13275 */
13276__isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
13277 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13278{
13279 isl_constraint *c;
13280 isl_space *space;
13281
13282 if (type1 == type2 && pos1 == pos2)
13283 return map;
13284 space = isl_map_get_space(map);
13285 c = constraint_order_ge(space, type1, pos1, type2, pos2);
13286 map = isl_map_add_constraint(map, c);
13287
13288 return map;
13289}
13290
13291/* Add a constraint imposing that the value of the first dimension is
13292 * less than or equal to that of the second.
13293 */
13294__isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
13295 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13296{
13297 return isl_map_order_ge(map, type2, pos2, type1, pos1);
13298}
13299
13300/* Construct a basic map where the value of the first dimension is
13301 * greater than that of the second.
13302 */
13303static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
13304 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13305{
13306 isl_basic_map *bmap = NULL;
13307 int i;
13308 isl_size total;
13309
13310 if (isl_space_check_range(space, type1, pos1, 1) < 0 ||
13311 isl_space_check_range(space, type2, pos2, 1) < 0)
13312 goto error;
13313
13314 if (type1 == type2 && pos1 == pos2)
13315 return isl_basic_map_empty(space);
13316
13317 bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
13318 total = isl_basic_map_dim(bmap, isl_dim_all);
13319 i = isl_basic_map_alloc_inequality(bmap);
13320 if (total < 0 || i < 0)
13321 return isl_basic_map_free(bmap);
13322 isl_seq_clr(bmap->ineq[i], 1 + total);
13323 pos1 += isl_basic_map_offset(bmap, type1);
13324 pos2 += isl_basic_map_offset(bmap, type2);
13325 isl_int_set_si(bmap->ineq[i][pos1], 1);
13326 isl_int_set_si(bmap->ineq[i][pos2], -1);
13327 isl_int_set_si(bmap->ineq[i][0], -1);
13328 bmap = isl_basic_map_finalize(bmap);
13329
13330 return bmap;
13331error:
13332 isl_space_free(space);
13333 isl_basic_map_free(bmap);
13334 return NULL;
13335}
13336
13337/* Add a constraint imposing that the value of the first dimension is
13338 * greater than that of the second.
13339 */
13340__isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
13341 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13342{
13343 isl_basic_map *gt;
13344
13345 gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
13346
13347 bmap = isl_basic_map_intersect(bmap, gt);
13348
13349 return bmap;
13350}
13351
13352/* Add a constraint imposing that the value of the first dimension is
13353 * greater than that of the second.
13354 */
13355__isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
13356 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13357{
13358 isl_basic_map *bmap;
13359
13360 bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
13361
13362 map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
13363
13364 return map;
13365}
13366
13367/* Add a constraint imposing that the value of the first dimension is
13368 * smaller than that of the second.
13369 */
13370__isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
13371 enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
13372{
13373 return isl_map_order_gt(map, type2, pos2, type1, pos1);
13374}
13375
13376__isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
13377 int pos)
13378{
13379 isl_aff *div;
13380 isl_local_space *ls;
13381
13382 if (!bmap)
13383 return NULL;
13384
13385 if (!isl_basic_map_divs_known(bmap))
13386 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13387 "some divs are unknown", return NULL);
13388
13389 ls = isl_basic_map_get_local_space(bmap);
13390 div = isl_local_space_get_div(ls, pos);
13391 isl_local_space_free(ls);
13392
13393 return div;
13394}
13395
13396__isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
13397 int pos)
13398{
13399 return isl_basic_map_get_div(bset, pos);
13400}
13401
13402/* Plug in "subs" for dimension "type", "pos" of "bset".
13403 *
13404 * Let i be the dimension to replace and let "subs" be of the form
13405 *
13406 * f/d
13407 *
13408 * Any integer division with a non-zero coefficient for i,
13409 *
13410 * floor((a i + g)/m)
13411 *
13412 * is replaced by
13413 *
13414 * floor((a f + d g)/(m d))
13415 *
13416 * Constraints of the form
13417 *
13418 * a i + g
13419 *
13420 * are replaced by
13421 *
13422 * a f + d g
13423 *
13424 * We currently require that "subs" is an integral expression.
13425 * Handling rational expressions may require us to add stride constraints
13426 * as we do in isl_basic_set_preimage_multi_aff.
13427 */
13428__isl_give isl_basic_set *isl_basic_set_substitute(
13429 __isl_take isl_basic_set *bset,
13430 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
13431{
13432 int i;
13433 isl_int v;
13434 isl_ctx *ctx;
13435 isl_size n_div;
13436
13437 if (bset && isl_basic_set_plain_is_empty(bset))
13438 return bset;
13439
13440 bset = isl_basic_set_cow(bset);
13441 if (!bset || !subs)
13442 goto error;
13443
13444 ctx = isl_basic_set_get_ctx(bset);
13445 if (!isl_space_is_equal(bset->dim, subs->ls->dim))
13446 isl_die(ctx, isl_error_invalid,
13447 "spaces don't match", goto error);
13448 n_div = isl_local_space_dim(subs->ls, isl_dim_div);
13449 if (n_div < 0)
13450 goto error;
13451 if (n_div != 0)
13452 isl_die(ctx, isl_error_unsupported,
13453 "cannot handle divs yet", goto error);
13454 if (!isl_int_is_one(subs->v->el[0]))
13455 isl_die(ctx, isl_error_invalid,
13456 "can only substitute integer expressions", goto error);
13457
13458 pos += isl_basic_set_offset(bset, type);
13459
13460 isl_int_init(v);
13461
13462 for (i = 0; i < bset->n_eq; ++i) {
13463 if (isl_int_is_zero(bset->eq[i][pos]))
13464 continue;
13465 isl_int_set(v, bset->eq[i][pos]);
13466 isl_int_set_si(bset->eq[i][pos], 0);
13467 isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
13468 v, subs->v->el + 1, subs->v->size - 1);
13469 }
13470
13471 for (i = 0; i < bset->n_ineq; ++i) {
13472 if (isl_int_is_zero(bset->ineq[i][pos]))
13473 continue;
13474 isl_int_set(v, bset->ineq[i][pos]);
13475 isl_int_set_si(bset->ineq[i][pos], 0);
13476 isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
13477 v, subs->v->el + 1, subs->v->size - 1);
13478 }
13479
13480 for (i = 0; i < bset->n_div; ++i) {
13481 if (isl_int_is_zero(bset->div[i][1 + pos]))
13482 continue;
13483 isl_int_set(v, bset->div[i][1 + pos]);
13484 isl_int_set_si(bset->div[i][1 + pos], 0);
13485 isl_seq_combine(bset->div[i] + 1,
13486 subs->v->el[0], bset->div[i] + 1,
13487 v, subs->v->el + 1, subs->v->size - 1);
13488 isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
13489 }
13490
13491 isl_int_clear(v);
13492
13493 bset = isl_basic_set_simplify(bset);
13494 return isl_basic_set_finalize(bset);
13495error:
13496 isl_basic_set_free(bset);
13497 return NULL;
13498}
13499
13500/* Plug in "subs" for dimension "type", "pos" of "set".
13501 */
13502__isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
13503 enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
13504{
13505 int i;
13506
13507 if (set && isl_set_plain_is_empty(set))
13508 return set;
13509
13510 set = isl_set_cow(set);
13511 if (!set || !subs)
13512 goto error;
13513
13514 for (i = set->n - 1; i >= 0; --i) {
13515 set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
13516 set = set_from_map(remove_if_empty(set_to_map(set), i));
13517 if (!set)
13518 return NULL;
13519 }
13520
13521 return set;
13522error:
13523 isl_set_free(set);
13524 return NULL;
13525}
13526
13527/* Check if the range of "ma" is compatible with the domain or range
13528 * (depending on "type") of "bmap".
13529 */
13530static isl_stat check_basic_map_compatible_range_multi_aff(
13531 __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
13532 __isl_keep isl_multi_aff *ma)
13533{
13534 isl_bool m;
13535 isl_space *ma_space;
13536
13537 ma_space = isl_multi_aff_get_space(ma);
13538
13539 m = isl_space_has_equal_params(bmap->dim, ma_space);
13540 if (m < 0)
13541 goto error;
13542 if (!m)
13543 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13544 "parameters don't match", goto error);
13545 m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
13546 if (m < 0)
13547 goto error;
13548 if (!m)
13549 isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
13550 "spaces don't match", goto error);
13551
13552 isl_space_free(ma_space);
13553 return isl_stat_ok;
13554error:
13555 isl_space_free(ma_space);
13556 return isl_stat_error;
13557}
13558
13559/* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
13560 * coefficients before the transformed range of dimensions,
13561 * the "n_after" coefficients after the transformed range of dimensions
13562 * and the coefficients of the other divs in "bmap".
13563 */
13564static __isl_give isl_basic_map *set_ma_divs(__isl_take isl_basic_map *bmap,
13565 __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
13566{
13567 int i;
13568 isl_size n_param;
13569 isl_size n_set;
13570 isl_local_space *ls;
13571
13572 if (n_div == 0)
13573 return bmap;
13574
13575 ls = isl_aff_get_domain_local_space(ma->u.p[0]);
13576 n_param = isl_local_space_dim(ls, isl_dim_param);
13577 n_set = isl_local_space_dim(ls, isl_dim_set);
13578 if (n_param < 0 || n_set < 0)
13579 return isl_basic_map_free(bmap);
13580
13581 for (i = 0; i < n_div; ++i) {
13582 int o_bmap = 0, o_ls = 0;
13583
13584 isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
13585 o_bmap += 1 + 1 + n_param;
13586 o_ls += 1 + 1 + n_param;
13587 isl_seq_clr(bmap->div[i] + o_bmap, n_before);
13588 o_bmap += n_before;
13589 isl_seq_cpy(bmap->div[i] + o_bmap,
13590 ls->div->row[i] + o_ls, n_set);
13591 o_bmap += n_set;
13592 o_ls += n_set;
13593 isl_seq_clr(bmap->div[i] + o_bmap, n_after);
13594 o_bmap += n_after;
13595 isl_seq_cpy(bmap->div[i] + o_bmap,
13596 ls->div->row[i] + o_ls, n_div);
13597 o_bmap += n_div;
13598 o_ls += n_div;
13599 isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
13600 bmap = isl_basic_map_add_div_constraints(bmap, i);
13601 if (!bmap)
13602 goto error;
13603 }
13604
13605 isl_local_space_free(ls);
13606 return bmap;
13607error:
13608 isl_local_space_free(ls);
13609 return isl_basic_map_free(bmap);
13610}
13611
13612/* How many stride constraints does "ma" enforce?
13613 * That is, how many of the affine expressions have a denominator
13614 * different from one?
13615 */
13616static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
13617{
13618 int i;
13619 int strides = 0;
13620
13621 for (i = 0; i < ma->n; ++i)
13622 if (!isl_int_is_one(ma->u.p[i]->v->el[0]))
13623 strides++;
13624
13625 return strides;
13626}
13627
13628/* For each affine expression in ma of the form
13629 *
13630 * x_i = (f_i y + h_i)/m_i
13631 *
13632 * with m_i different from one, add a constraint to "bmap"
13633 * of the form
13634 *
13635 * f_i y + h_i = m_i alpha_i
13636 *
13637 * with alpha_i an additional existentially quantified variable.
13638 *
13639 * The input variables of "ma" correspond to a subset of the variables
13640 * of "bmap". There are "n_before" variables in "bmap" before this
13641 * subset and "n_after" variables after this subset.
13642 * The integer divisions of the affine expressions in "ma" are assumed
13643 * to have been aligned. There are "n_div_ma" of them and
13644 * they appear first in "bmap", straight after the "n_after" variables.
13645 */
13646static __isl_give isl_basic_map *add_ma_strides(
13647 __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
13648 int n_before, int n_after, int n_div_ma)
13649{
13650 int i, k;
13651 int div;
13652 isl_size total;
13653 isl_size n_param;
13654 isl_size n_in;
13655
13656 total = isl_basic_map_dim(bmap, isl_dim_all);
13657 n_param = isl_multi_aff_dim(ma, isl_dim_param);
13658 n_in = isl_multi_aff_dim(ma, isl_dim_in);
13659 if (total < 0 || n_param < 0 || n_in < 0)
13660 return isl_basic_map_free(bmap);
13661 for (i = 0; i < ma->n; ++i) {
13662 int o_bmap = 0, o_ma = 1;
13663
13664 if (isl_int_is_one(ma->u.p[i]->v->el[0]))
13665 continue;
13666 div = isl_basic_map_alloc_div(bmap);
13667 k = isl_basic_map_alloc_equality(bmap);
13668 if (div < 0 || k < 0)
13669 goto error;
13670 isl_int_set_si(bmap->div[div][0], 0);
13671 isl_seq_cpy(bmap->eq[k] + o_bmap,
13672 ma->u.p[i]->v->el + o_ma, 1 + n_param);
13673 o_bmap += 1 + n_param;
13674 o_ma += 1 + n_param;
13675 isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
13676 o_bmap += n_before;
13677 isl_seq_cpy(bmap->eq[k] + o_bmap,
13678 ma->u.p[i]->v->el + o_ma, n_in);
13679 o_bmap += n_in;
13680 o_ma += n_in;
13681 isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
13682 o_bmap += n_after;
13683 isl_seq_cpy(bmap->eq[k] + o_bmap,
13684 ma->u.p[i]->v->el + o_ma, n_div_ma);
13685 o_bmap += n_div_ma;
13686 o_ma += n_div_ma;
13687 isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
13688 isl_int_neg(bmap->eq[k][1 + total], ma->u.p[i]->v->el[0]);
13689 total++;
13690 }
13691
13692 return bmap;
13693error:
13694 isl_basic_map_free(bmap);
13695 return NULL;
13696}
13697
13698/* Replace the domain or range space (depending on "type) of "space" by "set".
13699 */
13700static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
13701 enum isl_dim_type type, __isl_take isl_space *set)
13702{
13703 if (type == isl_dim_in) {
13704 space = isl_space_range(space);
13705 space = isl_space_map_from_domain_and_range(set, space);
13706 } else {
13707 space = isl_space_domain(space);
13708 space = isl_space_map_from_domain_and_range(space, set);
13709 }
13710
13711 return space;
13712}
13713
13714/* Compute the preimage of the domain or range (depending on "type")
13715 * of "bmap" under the function represented by "ma".
13716 * In other words, plug in "ma" in the domain or range of "bmap".
13717 * The result is a basic map that lives in the same space as "bmap"
13718 * except that the domain or range has been replaced by
13719 * the domain space of "ma".
13720 *
13721 * If bmap is represented by
13722 *
13723 * A(p) + S u + B x + T v + C(divs) >= 0,
13724 *
13725 * where u and x are input and output dimensions if type == isl_dim_out
13726 * while x and v are input and output dimensions if type == isl_dim_in,
13727 * and ma is represented by
13728 *
13729 * x = D(p) + F(y) + G(divs')
13730 *
13731 * then the result is
13732 *
13733 * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
13734 *
13735 * The divs in the input set are similarly adjusted.
13736 * In particular
13737 *
13738 * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
13739 *
13740 * becomes
13741 *
13742 * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
13743 * B_i G(divs') + c_i(divs))/n_i)
13744 *
13745 * If bmap is not a rational map and if F(y) involves any denominators
13746 *
13747 * x_i = (f_i y + h_i)/m_i
13748 *
13749 * then additional constraints are added to ensure that we only
13750 * map back integer points. That is we enforce
13751 *
13752 * f_i y + h_i = m_i alpha_i
13753 *
13754 * with alpha_i an additional existentially quantified variable.
13755 *
13756 * We first copy over the divs from "ma".
13757 * Then we add the modified constraints and divs from "bmap".
13758 * Finally, we add the stride constraints, if needed.
13759 */
13760__isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
13761 __isl_take isl_basic_map *bmap, enum isl_dim_type type,
13762 __isl_take isl_multi_aff *ma)
13763{
13764 int i, k;
13765 isl_space *space;
13766 isl_basic_map *res = NULL;
13767 isl_size n_before, n_after, n_div_bmap, n_div_ma;
13768 isl_int f, c1, c2, g;
13769 isl_bool rational;
13770 int strides;
13771
13772 isl_int_init(f);
13773 isl_int_init(c1);
13774 isl_int_init(c2);
13775 isl_int_init(g);
13776
13777 ma = isl_multi_aff_align_divs(ma);
13778 if (!bmap || !ma)
13779 goto error;
13780 if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
13781 goto error;
13782
13783 if (type == isl_dim_in) {
13784 n_before = 0;
13785 n_after = isl_basic_map_dim(bmap, isl_dim_out);
13786 } else {
13787 n_before = isl_basic_map_dim(bmap, isl_dim_in);
13788 n_after = 0;
13789 }
13790 n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
13791 n_div_ma = ma->n ? isl_aff_dim(ma->u.p[0], isl_dim_div) : 0;
13792 if (n_before < 0 || n_after < 0 || n_div_bmap < 0 || n_div_ma < 0)
13793 goto error;
13794
13795 space = isl_multi_aff_get_domain_space(ma);
13796 space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
13797 rational = isl_basic_map_is_rational(bmap);
13798 strides = rational ? 0 : multi_aff_strides(ma);
13799 res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
13800 bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
13801 if (rational)
13802 res = isl_basic_map_set_rational(res);
13803
13804 for (i = 0; i < n_div_ma + n_div_bmap; ++i)
13805 if (isl_basic_map_alloc_div(res) < 0)
13806 goto error;
13807
13808 res = set_ma_divs(res, ma, n_before, n_after, n_div_ma);
13809 if (!res)
13810 goto error;
13811
13812 for (i = 0; i < bmap->n_eq; ++i) {
13813 k = isl_basic_map_alloc_equality(res);
13814 if (k < 0)
13815 goto error;
13816 if (isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
13817 n_after, n_div_ma, n_div_bmap,
13818 f, c1, c2, g, 0) < 0)
13819 goto error;
13820 }
13821
13822 for (i = 0; i < bmap->n_ineq; ++i) {
13823 k = isl_basic_map_alloc_inequality(res);
13824 if (k < 0)
13825 goto error;
13826 if (isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
13827 n_after, n_div_ma, n_div_bmap,
13828 f, c1, c2, g, 0) < 0)
13829 goto error;
13830 }
13831
13832 for (i = 0; i < bmap->n_div; ++i) {
13833 if (isl_int_is_zero(bmap->div[i][0])) {
13834 isl_int_set_si(res->div[n_div_ma + i][0], 0);
13835 continue;
13836 }
13837 if (isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
13838 n_before, n_after, n_div_ma, n_div_bmap,
13839 f, c1, c2, g, 1) < 0)
13840 goto error;
13841 }
13842
13843 if (strides)
13844 res = add_ma_strides(res, ma, n_before, n_after, n_div_ma);
13845
13846 isl_int_clear(f);
13847 isl_int_clear(c1);
13848 isl_int_clear(c2);
13849 isl_int_clear(g);
13850 isl_basic_map_free(bmap);
13851 isl_multi_aff_free(ma);
13852 res = isl_basic_map_simplify(res);
13853 return isl_basic_map_finalize(res);
13854error:
13855 isl_int_clear(f);
13856 isl_int_clear(c1);
13857 isl_int_clear(c2);
13858 isl_int_clear(g);
13859 isl_basic_map_free(bmap);
13860 isl_multi_aff_free(ma);
13861 isl_basic_map_free(res);
13862 return NULL;
13863}
13864
13865/* Compute the preimage of "bset" under the function represented by "ma".
13866 * In other words, plug in "ma" in "bset". The result is a basic set
13867 * that lives in the domain space of "ma".
13868 */
13869__isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
13870 __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
13871{
13872 return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
13873}
13874
13875/* Compute the preimage of the domain of "bmap" under the function
13876 * represented by "ma".
13877 * In other words, plug in "ma" in the domain of "bmap".
13878 * The result is a basic map that lives in the same space as "bmap"
13879 * except that the domain has been replaced by the domain space of "ma".
13880 */
13881__isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
13882 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13883{
13884 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
13885}
13886
13887/* Compute the preimage of the range of "bmap" under the function
13888 * represented by "ma".
13889 * In other words, plug in "ma" in the range of "bmap".
13890 * The result is a basic map that lives in the same space as "bmap"
13891 * except that the range has been replaced by the domain space of "ma".
13892 */
13893__isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
13894 __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
13895{
13896 return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
13897}
13898
13899/* Check if the range of "ma" is compatible with the domain or range
13900 * (depending on "type") of "map".
13901 * Return isl_stat_error if anything is wrong.
13902 */
13903static isl_stat check_map_compatible_range_multi_aff(
13904 __isl_keep isl_map *map, enum isl_dim_type type,
13905 __isl_keep isl_multi_aff *ma)
13906{
13907 isl_bool m;
13908 isl_space *ma_space;
13909
13910 ma_space = isl_multi_aff_get_space(ma);
13911 m = isl_map_space_tuple_is_equal(map, type, ma_space, isl_dim_out);
13912 isl_space_free(ma_space);
13913 if (m < 0)
13914 return isl_stat_error;
13915 if (!m)
13916 isl_die(isl_map_get_ctx(map), isl_error_invalid,
13917 "spaces don't match", return isl_stat_error);
13918 return isl_stat_ok;
13919}
13920
13921/* Compute the preimage of the domain or range (depending on "type")
13922 * of "map" under the function represented by "ma".
13923 * In other words, plug in "ma" in the domain or range of "map".
13924 * The result is a map that lives in the same space as "map"
13925 * except that the domain or range has been replaced by
13926 * the domain space of "ma".
13927 *
13928 * The parameters are assumed to have been aligned.
13929 */
13930static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
13931 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13932{
13933 int i;
13934 isl_space *space;
13935
13936 map = isl_map_cow(map);
13937 ma = isl_multi_aff_align_divs(ma);
13938 if (!map || !ma)
13939 goto error;
13940 if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
13941 goto error;
13942
13943 for (i = 0; i < map->n; ++i) {
13944 map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
13945 isl_multi_aff_copy(ma));
13946 if (!map->p[i])
13947 goto error;
13948 }
13949
13950 space = isl_multi_aff_get_domain_space(ma);
13951 space = isl_space_set(isl_map_get_space(map), type, space);
13952
13953 isl_space_free(isl_map_take_space(map));
13954 map = isl_map_restore_space(map, space);
13955 if (!map)
13956 goto error;
13957
13958 isl_multi_aff_free(ma);
13959 if (map->n > 1)
13960 ISL_F_CLR(map, ISL_MAP_DISJOINT);
13961 ISL_F_CLR(map, ISL_SET_NORMALIZED);
13962 return map;
13963error:
13964 isl_multi_aff_free(ma);
13965 isl_map_free(map);
13966 return NULL;
13967}
13968
13969/* Compute the preimage of the domain or range (depending on "type")
13970 * of "map" under the function represented by "ma".
13971 * In other words, plug in "ma" in the domain or range of "map".
13972 * The result is a map that lives in the same space as "map"
13973 * except that the domain or range has been replaced by
13974 * the domain space of "ma".
13975 */
13976__isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
13977 enum isl_dim_type type, __isl_take isl_multi_aff *ma)
13978{
13979 isl_bool aligned;
13980
13981 if (!map || !ma)
13982 goto error;
13983
13984 aligned = isl_map_space_has_equal_params(map, ma->space);
13985 if (aligned < 0)
13986 goto error;
13987 if (aligned)
13988 return map_preimage_multi_aff(map, type, ma);
13989
13990 if (isl_map_check_named_params(map) < 0)
13991 goto error;
13992 if (!isl_space_has_named_params(ma->space))
13993 isl_die(map->ctx, isl_error_invalid,
13994 "unaligned unnamed parameters", goto error);
13995 map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
13996 ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
13997
13998 return map_preimage_multi_aff(map, type, ma);
13999error:
14000 isl_multi_aff_free(ma);
14001 return isl_map_free(map);
14002}
14003
14004/* Compute the preimage of "set" under the function represented by "ma".
14005 * In other words, plug in "ma" in "set". The result is a set
14006 * that lives in the domain space of "ma".
14007 */
14008__isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
14009 __isl_take isl_multi_aff *ma)
14010{
14011 return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
14012}
14013
14014/* Compute the preimage of the domain of "map" under the function
14015 * represented by "ma".
14016 * In other words, plug in "ma" in the domain of "map".
14017 * The result is a map that lives in the same space as "map"
14018 * except that the domain has been replaced by the domain space of "ma".
14019 */
14020__isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
14021 __isl_take isl_multi_aff *ma)
14022{
14023 return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
14024}
14025
14026/* Compute the preimage of the range of "map" under the function
14027 * represented by "ma".
14028 * In other words, plug in "ma" in the range of "map".
14029 * The result is a map that lives in the same space as "map"
14030 * except that the range has been replaced by the domain space of "ma".
14031 */
14032__isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
14033 __isl_take isl_multi_aff *ma)
14034{
14035 return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
14036}
14037
14038/* Compute the preimage of "map" under the function represented by "pma".
14039 * In other words, plug in "pma" in the domain or range of "map".
14040 * The result is a map that lives in the same space as "map",
14041 * except that the space of type "type" has been replaced by
14042 * the domain space of "pma".
14043 *
14044 * The parameters of "map" and "pma" are assumed to have been aligned.
14045 */
14046static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
14047 __isl_take isl_map *map, enum isl_dim_type type,
14048 __isl_take isl_pw_multi_aff *pma)
14049{
14050 int i;
14051 isl_map *res;
14052
14053 if (!pma)
14054 goto error;
14055
14056 if (pma->n == 0) {
14057 isl_pw_multi_aff_free(pma);
14058 res = isl_map_empty(isl_map_get_space(map));
14059 isl_map_free(map);
14060 return res;
14061 }
14062
14063 res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14064 isl_multi_aff_copy(pma->p[0].maff));
14065 if (type == isl_dim_in)
14066 res = isl_map_intersect_domain(res,
14067 isl_map_copy(pma->p[0].set));
14068 else
14069 res = isl_map_intersect_range(res,
14070 isl_map_copy(pma->p[0].set));
14071
14072 for (i = 1; i < pma->n; ++i) {
14073 isl_map *res_i;
14074
14075 res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
14076 isl_multi_aff_copy(pma->p[i].maff));
14077 if (type == isl_dim_in)
14078 res_i = isl_map_intersect_domain(res_i,
14079 isl_map_copy(pma->p[i].set));
14080 else
14081 res_i = isl_map_intersect_range(res_i,
14082 isl_map_copy(pma->p[i].set));
14083 res = isl_map_union(res, res_i);
14084 }
14085
14086 isl_pw_multi_aff_free(pma);
14087 isl_map_free(map);
14088 return res;
14089error:
14090 isl_pw_multi_aff_free(pma);
14091 isl_map_free(map);
14092 return NULL;
14093}
14094
14095/* Compute the preimage of "map" under the function represented by "pma".
14096 * In other words, plug in "pma" in the domain or range of "map".
14097 * The result is a map that lives in the same space as "map",
14098 * except that the space of type "type" has been replaced by
14099 * the domain space of "pma".
14100 */
14101__isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
14102 enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
14103{
14104 isl_bool aligned;
14105
14106 if (!map || !pma)
14107 goto error;
14108
14109 aligned = isl_map_space_has_equal_params(map, pma->dim);
14110 if (aligned < 0)
14111 goto error;
14112 if (aligned)
14113 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14114
14115 if (isl_map_check_named_params(map) < 0)
14116 goto error;
14117 if (isl_pw_multi_aff_check_named_params(pma) < 0)
14118 goto error;
14119 map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
14120 pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
14121
14122 return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
14123error:
14124 isl_pw_multi_aff_free(pma);
14125 return isl_map_free(map);
14126}
14127
14128/* Compute the preimage of "set" under the function represented by "pma".
14129 * In other words, plug in "pma" in "set". The result is a set
14130 * that lives in the domain space of "pma".
14131 */
14132__isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
14133 __isl_take isl_pw_multi_aff *pma)
14134{
14135 return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
14136}
14137
14138/* Compute the preimage of the domain of "map" under the function
14139 * represented by "pma".
14140 * In other words, plug in "pma" in the domain of "map".
14141 * The result is a map that lives in the same space as "map",
14142 * except that domain space has been replaced by the domain space of "pma".
14143 */
14144__isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
14145 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14146{
14147 return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
14148}
14149
14150/* Compute the preimage of the range of "map" under the function
14151 * represented by "pma".
14152 * In other words, plug in "pma" in the range of "map".
14153 * The result is a map that lives in the same space as "map",
14154 * except that range space has been replaced by the domain space of "pma".
14155 */
14156__isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
14157 __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
14158{
14159 return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
14160}
14161
14162/* Compute the preimage of "map" under the function represented by "mpa".
14163 * In other words, plug in "mpa" in the domain or range of "map".
14164 * The result is a map that lives in the same space as "map",
14165 * except that the space of type "type" has been replaced by
14166 * the domain space of "mpa".
14167 *
14168 * If the map does not involve any constraints that refer to the
14169 * dimensions of the substituted space, then the only possible
14170 * effect of "mpa" on the map is to map the space to a different space.
14171 * We create a separate isl_multi_aff to effectuate this change
14172 * in order to avoid spurious splitting of the map along the pieces
14173 * of "mpa".
14174 * If "mpa" has a non-trivial explicit domain, however,
14175 * then the full substitution should be performed.
14176 */
14177__isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
14178 enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
14179{
14180 isl_size n;
14181 isl_bool full;
14182 isl_pw_multi_aff *pma;
14183
14184 n = isl_map_dim(map, type);
14185 if (n < 0 || !mpa)
14186 goto error;
14187
14188 full = isl_map_involves_dims(map, type, 0, n);
14189 if (full >= 0 && !full)
14190 full = isl_multi_pw_aff_has_non_trivial_domain(mpa);
14191 if (full < 0)
14192 goto error;
14193 if (!full) {
14194 isl_space *space;
14195 isl_multi_aff *ma;
14196
14197 space = isl_multi_pw_aff_get_space(mpa);
14198 isl_multi_pw_aff_free(mpa);
14199 ma = isl_multi_aff_zero(space);
14200 return isl_map_preimage_multi_aff(map, type, ma);
14201 }
14202
14203 pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
14204 return isl_map_preimage_pw_multi_aff(map, type, pma);
14205error:
14206 isl_map_free(map);
14207 isl_multi_pw_aff_free(mpa);
14208 return NULL;
14209}
14210
14211/* Compute the preimage of "map" under the function represented by "mpa".
14212 * In other words, plug in "mpa" in the domain "map".
14213 * The result is a map that lives in the same space as "map",
14214 * except that domain space has been replaced by the domain space of "mpa".
14215 */
14216__isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
14217 __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
14218{
14219 return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
14220}
14221
14222/* Compute the preimage of "set" by the function represented by "mpa".
14223 * In other words, plug in "mpa" in "set".
14224 */
14225__isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
14226 __isl_take isl_multi_pw_aff *mpa)
14227{
14228 return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
14229}
14230
14231/* Return a copy of the equality constraints of "bset" as a matrix.
14232 */
14233__isl_give isl_mat *isl_basic_set_extract_equalities(
14234 __isl_keep isl_basic_set *bset)
14235{
14236 isl_ctx *ctx;
14237 isl_size total;
14238
14239 total = isl_basic_set_dim(bset, isl_dim_all);
14240 if (total < 0)
14241 return NULL;
14242
14243 ctx = isl_basic_set_get_ctx(bset);
14244 return isl_mat_sub_alloc6(ctx, bset->eq, 0, bset->n_eq, 0, 1 + total);
14245}
14246
14247/* Are the "n" "coefficients" starting at "first" of the integer division
14248 * expressions at position "pos1" in "bmap1" and "pos2" in "bmap2" equal
14249 * to each other?
14250 * The "coefficient" at position 0 is the denominator.
14251 * The "coefficient" at position 1 is the constant term.
14252 */
14253isl_bool isl_basic_map_equal_div_expr_part(__isl_keep isl_basic_map *bmap1,
14254 int pos1, __isl_keep isl_basic_map *bmap2, int pos2,
14255 unsigned first, unsigned n)
14256{
14257 if (isl_basic_map_check_range(bmap1, isl_dim_div, pos1, 1) < 0)
14258 return isl_bool_error;
14259 if (isl_basic_map_check_range(bmap2, isl_dim_div, pos2, 1) < 0)
14260 return isl_bool_error;
14261 return isl_seq_eq(bmap1->div[pos1] + first,
14262 bmap2->div[pos2] + first, n);
14263}
14264
14265/* Are the integer division expressions at position "pos1" in "bmap1" and
14266 * "pos2" in "bmap2" equal to each other, except that the constant terms
14267 * are different?
14268 */
14269isl_bool isl_basic_map_equal_div_expr_except_constant(
14270 __isl_keep isl_basic_map *bmap1, int pos1,
14271 __isl_keep isl_basic_map *bmap2, int pos2)
14272{
14273 isl_bool equal;
14274 isl_size total, total2;
14275
14276 total = isl_basic_map_dim(bmap1, isl_dim_all);
14277 total2 = isl_basic_map_dim(bmap2, isl_dim_all);
14278 if (total < 0 || total2 < 0)
14279 return isl_bool_error;
14280 if (total != total2)
14281 isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
14282 "incomparable div expressions", return isl_bool_error);
14283 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14284 0, 1);
14285 if (equal < 0 || !equal)
14286 return equal;
14287 equal = isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14288 1, 1);
14289 if (equal < 0 || equal)
14290 return isl_bool_not(equal);
14291 return isl_basic_map_equal_div_expr_part(bmap1, pos1, bmap2, pos2,
14292 2, total);
14293}
14294
14295/* Replace the numerator of the constant term of the integer division
14296 * expression at position "div" in "bmap" by "value".
14297 * The caller guarantees that this does not change the meaning
14298 * of the input.
14299 */
14300__isl_give isl_basic_map *isl_basic_map_set_div_expr_constant_num_si_inplace(
14301 __isl_take isl_basic_map *bmap, int div, int value)
14302{
14303 if (isl_basic_map_check_range(bmap, isl_dim_div, div, 1) < 0)
14304 return isl_basic_map_free(bmap);
14305
14306 isl_int_set_si(bmap->div[div][1], value);
14307
14308 return bmap;
14309}
14310
14311/* Is the point "inner" internal to inequality constraint "ineq"
14312 * of "bset"?
14313 * The point is considered to be internal to the inequality constraint,
14314 * if it strictly lies on the positive side of the inequality constraint,
14315 * or if it lies on the constraint and the constraint is lexico-positive.
14316 */
14317static isl_bool is_internal(__isl_keep isl_vec *inner,
14318 __isl_keep isl_basic_set *bset, int ineq)
14319{
14320 isl_ctx *ctx;
14321 int pos;
14322 isl_size total;
14323
14324 if (!inner || !bset)
14325 return isl_bool_error;
14326
14327 ctx = isl_basic_set_get_ctx(bset);
14328 isl_seq_inner_product(inner->el, bset->ineq[ineq], inner->size,
14329 &ctx->normalize_gcd);
14330 if (!isl_int_is_zero(ctx->normalize_gcd))
14331 return isl_int_is_nonneg(ctx->normalize_gcd);
14332
14333 total = isl_basic_set_dim(bset, isl_dim_all);
14334 if (total < 0)
14335 return isl_bool_error;
14336 pos = isl_seq_first_non_zero(bset->ineq[ineq] + 1, total);
14337 return isl_int_is_pos(bset->ineq[ineq][1 + pos]);
14338}
14339
14340/* Tighten the inequality constraints of "bset" that are outward with respect
14341 * to the point "vec".
14342 * That is, tighten the constraints that are not satisfied by "vec".
14343 *
14344 * "vec" is a point internal to some superset S of "bset" that is used
14345 * to make the subsets of S disjoint, by tightening one half of the constraints
14346 * that separate two subsets. In particular, the constraints of S
14347 * are all satisfied by "vec" and should not be tightened.
14348 * Of the internal constraints, those that have "vec" on the outside
14349 * are tightened. The shared facet is included in the adjacent subset
14350 * with the opposite constraint.
14351 * For constraints that saturate "vec", this criterion cannot be used
14352 * to determine which of the two sides should be tightened.
14353 * Instead, the sign of the first non-zero coefficient is used
14354 * to make this choice. Note that this second criterion is never used
14355 * on the constraints of S since "vec" is interior to "S".
14356 */
14357__isl_give isl_basic_set *isl_basic_set_tighten_outward(
14358 __isl_take isl_basic_set *bset, __isl_keep isl_vec *vec)
14359{
14360 int j;
14361
14362 bset = isl_basic_set_cow(bset);
14363 if (!bset)
14364 return NULL;
14365 for (j = 0; j < bset->n_ineq; ++j) {
14366 isl_bool internal;
14367
14368 internal = is_internal(vec, bset, j);
14369 if (internal < 0)
14370 return isl_basic_set_free(bset);
14371 if (internal)
14372 continue;
14373 isl_int_sub_ui(bset->ineq[j][0], bset->ineq[j][0], 1);
14374 }
14375
14376 return bset;
14377}
14378
14379/* Replace the variables x of type "type" starting at "first" in "bmap"
14380 * by x' with x = M x' with M the matrix trans.
14381 * That is, replace the corresponding coefficients c by c M.
14382 *
14383 * The transformation matrix should be a square matrix.
14384 */
14385__isl_give isl_basic_map *isl_basic_map_transform_dims(
14386 __isl_take isl_basic_map *bmap, enum isl_dim_type type, unsigned first,
14387 __isl_take isl_mat *trans)
14388{
14389 unsigned pos;
14390
14391 bmap = isl_basic_map_cow(bmap);
14392 if (!bmap || !trans)
14393 goto error;
14394
14395 if (trans->n_row != trans->n_col)
14396 isl_die(trans->ctx, isl_error_invalid,
14397 "expecting square transformation matrix", goto error);
14398 if (isl_basic_map_check_range(bmap, type, first, trans->n_row) < 0)
14399 goto error;
14400
14401 pos = isl_basic_map_offset(bmap, type) + first;
14402
14403 if (isl_mat_sub_transform(bmap->eq, bmap->n_eq, pos,
14404 isl_mat_copy(trans)) < 0)
14405 goto error;
14406 if (isl_mat_sub_transform(bmap->ineq, bmap->n_ineq, pos,
14407 isl_mat_copy(trans)) < 0)
14408 goto error;
14409 if (isl_mat_sub_transform(bmap->div, bmap->n_div, 1 + pos,
14410 isl_mat_copy(trans)) < 0)
14411 goto error;
14412
14413 ISL_F_CLR(bmap, ISL_BASIC_MAP_SORTED);
14414 ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
14415
14416 isl_mat_free(trans);
14417 return bmap;
14418error:
14419 isl_mat_free(trans);
14420 isl_basic_map_free(bmap);
14421 return NULL;
14422}
14423
14424/* Replace the variables x of type "type" starting at "first" in "bset"
14425 * by x' with x = M x' with M the matrix trans.
14426 * That is, replace the corresponding coefficients c by c M.
14427 *
14428 * The transformation matrix should be a square matrix.
14429 */
14430__isl_give isl_basic_set *isl_basic_set_transform_dims(
14431 __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
14432 __isl_take isl_mat *trans)
14433{
14434 return isl_basic_map_transform_dims(bset, type, first, trans);
14435}
14436